速度比較検証

速度比較検証

VBAから扱えるDLLを作成したいと思い、Visual Studio 2017を利用しつくってみました。
参考:[VBAから扱えるDLLを作成] [VBAをVBに変換]

作成したのは数独を解析するDLLファイルです。VBAコード:Excelで数独解析 Ver.2.3.0

そもそも、なぜVBAから扱えるDLLを作成したのかは、より高速で数独を解析したいと考えたからです。 [世界最速への挑戦]
VBAはインタプリタ型言語(プログラム実行時にコードを機械語に翻訳する形式のプログラム)なので、コンパイラ型言語(予めコードを機械語に翻訳する形式のプログラム)より、実行速度が遅いと言われています。
DLLファイルは、コンパイルされているので、同じ内容であれば、VBAよりプログラムの実行速度が速くなることが期待されます。

無事にDLLができたので、どのくらい速くなるのかを検証してみました。
そのまとめのメモです。

検証内容

 ・数独の250問連続解析
 ・VBAコードの速度とDLLファイルコードの速度を比較

 ※検証の前提・・・Windows 10 / Intel(R) Core(TM) i7-3517U CPU 2.40GHz / Excel2007


VBAコード検証

検証用ファイル:検証を行ったExcelファイル。クリックでダウンロード。
検証・解析コード:検証コード。抜粋したものを以下に表示。
※本来の250問解析ファイルは、VBAで準備されているTimer関数を使っている。今回はより正確な時間の計測を行うため、Win32APIのtimeGetTime関数を使用した。

Option Explicit

#If VBA7 And Win64 Then      'VBAのVersion7で、64bitマシンの場合
    Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long
#Else 'それ以外
    Declare Function timeGetTime Lib "winmm.dll" () As Long
#End If

Type TTT
    varValue(1 To 9, 1 To 9) As Variant
    varKai As Variant
End Type
 
Public TB(1 To 250) As TTT
'-------------------------------------------------------------------------------------------------------

Sub Sample250()
 
    Dim i As Long, j As Long
    Dim ii As Long, jj As Long
    Dim lngTime As Long
    Dim strS As String
    Dim varVal As Variant
 
    With Application
        .ScreenUpdating = False
        With Worksheets(1)
            varVal = .Range("B1:J2250").Value
            For i = 1 To 250
                ii = (i - 1) * 9
                For j = 1 To 9
                    For jj = 1 To 9
                        TB(i).varValue(j, jj) = varVal(ii + j, jj)
                    Next
                Next
                TB(i).varKai = TB(i).varValue
            Next
            lngTime = timeGetTime()
            For i = 1 To 250
                If Sudoku_Kaiseki(TB(i).varKai, strS, True) <> 0 Then
                    MsgBox strS, vbExclamation + vbOKOnly, i & "問目": Exit Sub
                End If
            Next
            MsgBox timeGetTime() - lngTime & "ミリ秒"
            For i = 1 To 250
                ii = (i - 1) * 9
                For j = 1 To 9
                    For jj = 1 To 9
                        varVal(ii + j, jj) = TB(i).varKai(j, jj)
                    Next
                Next
            Next
            .Range("L1:T2250").Value = varVal
        End With
        .ScreenUpdating = True
    End With
End Sub
'-------------------------------------------------------------------------------------------------------

Sub Syoukyo250()
    Worksheets(1).Range("L1:T2250").ClearContents
End Sub

[ 結果 ]
VBAコードでの結果:250問解析に要した時間、217ミリ秒(0.217秒)


DLLファイル検証

検証用ファイル:検証用ファイル一式(Excel、DLLファイル他)。クリックでダウンロード
 ダウンロード時に警告がでるかもしれないが問題ない。
 警告の原因は、VBスプリクトファイルが含まれているため。

検証・解析コード:検証コード。VBAからDLLにアクセス。以下に表示。
※予め、DLLを登録する必要がある。同梱されているファイルで簡単に行える。DLLの登録
 このDLLファイルは、64bit版のExcelには対応していない。

Option Explicit

#If VBA7 And Win64 Then 'VBAのVersion7で、64bitマシンの場合
    Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long
#Else 'それ以外
    Declare Function timeGetTime Lib "winmm.dll" () As Long
#End If

Type TTT
    varKai(9, 9) As Long
End Type
 
Public TB(1 To 250) As TTT
'-------------------------------------------------------------------------------------------------------
 
Sub Sample250()
 
    Dim i As Long, j As Long
    Dim ii As Long, jj As Long
    Dim lngTime As Long
    Dim strS As String
    Dim varVal As Variant
    Dim clsSudoku As New Sudoku_Kaiseki.analysis_sudoku

    With Application
        .ScreenUpdating = False
        With Worksheets(1)
            varVal = .Range("B1:J2250").Value
            For i = 1 To 250
                ii = (i - 1) * 9
                For j = 1 To 9
                    For jj = 1 To 9
                        TB(i).varKai(j, jj) = varVal(ii + j, jj)
                    Next
                Next
            Next
            lngTime = timeGetTime()
            For i = 1 To 250
                If clsSudoku.Sudoku_Kaiseki_Main(TB(i).varKai, strS, True) <> 0 Then
                    MsgBox strS, vbExclamation + vbOKOnly, i & "問目": Exit Sub
                End If
            Next
            MsgBox timeGetTime() - lngTime & "ミリ秒"
            For i = 1 To 250
                ii = (i - 1) * 9
                For j = 1 To 9
                    For jj = 1 To 9
                        varVal(ii + j, jj) = TB(i).varKai(j, jj)
                    Next
                Next
            Next
            .Range("L1:T2250").Value = varVal
        End With
        .ScreenUpdating = True
    End With
End Sub
'-------------------------------------------------------------------------------------------------------

Sub Syoukyo250()
    Worksheets(1).Range("L1:T2250").ClearContents
End Sub

[ 結果 ]
DLLファイルを利用の結果:250問解析に要した時間、31ミリ秒(0.031秒)


まとめ

インタプリタ型であるVBAと、コンパイラ型のDLLファイルを、ほぼ同じ内容の処理で比較した結果、私の環境ではDLLファイルの方が約7倍速い結果となった。

今回検証に用いた数独と同難度の問題を、私のパソコン環境で解析を行う場合、理論上、VBAのみの場合は1秒間に1152問、DLLを用いると1秒間に8064問解析ができることがわかった。

※VBAとDLLの解析コードを比較しながら見る場合はこちら。コード比較 左[VB] 右[VBA]


DLLファイルの使用

DLLファイル検証の検証用ファイルに入っているDLLはご自由にご使用いただいて構いません。ただし、無許可での配布等はやめてください。連絡はこちら
同梱されているスクリプトファイルを用い、一度登録すると、Excelからいつでも数独を解析する関数を呼び出すことができます(用途は限定されていますが。。。)。

※ダウンロード時に警告がでるかもしれないが問題ない。警告の原因は、VBスプリクトファイルが含まれているため。

同梱されている説明書

ページトップに戻る

Excel Tips for Teachers

Copyright (C) 2009- 坂江 保 All Rights Reserved.