速度比較検証2017.11.04
VBAから扱えるDLLを作成したいと思い、Visual Studio 2017を利用しつくってみました。
参考:[VBAから扱えるDLLを作成] [VBAをVBに変換]
作成したのは数独を解析するDLLファイルです。VBAコード:Excelで数独解析 Ver.2.3.0
そもそも、なぜVBAから扱えるDLLを作成したのかは、数独をより高速に解析したいと考えたからです。 [世界最速への挑戦]
VBAはインタプリタ型言語(プログラム実行時にコードを機械語に翻訳する形式のプログラム)なので、コンパイラ型言語(予めコードを機械語に翻訳する形式のプログラム)より、実行速度が遅いと言われています。
DLLファイルは、コンパイルされているので、同じ内容であれば、VBAよりプログラムの実行速度が速くなることが期待されます。
無事にDLLができたので、どのくらい速くなるのかを検証してみました。
そのまとめのメモです。
検証内容
・数独の250問連続解析 ver.2.3.0
・VBAコードの速度とDLLファイルコードの速度を比較
※検証の前提・・・Windows 10 / Intel(R) Core(TM) i7-3517U CPU 2.40GHz / Excel2007
VBAコード検証
・検証用ファイル:検証を行ったExcelファイル。ダウンロード
・検証・解析コード:検証コード。抜粋したものを以下に表示。
※本来の250問解析ファイルは、VBAで準備されているTimer関数を使っている。今回はより正確な時間の計測を行うため、Win32APIのtimeGetTime関数を使用した。
#If VBA7 Then 'Excel2010以上 Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long #Else 'Excel2007以下 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ファイル他)。ダウンロード
ダウンロード時に警告がでるかもしれないが問題ない。
・検証・解析コード:検証コード。VBAからDLLにアクセス。以下に表示。
※予め、DLLを登録する必要がある。同梱されているファイルで簡単に行える。DLLの登録。
このDLLファイルは、64bit版のExcelには対応していない。
#If VBA7 Then 'Excel2010以上 Declare PtrSafe Function timeGetTime Lib "winmm.dll" () As Long #Else 'Excel2007以下 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問解析ができることがわかった。
コード比較: [VB] [VBA]
DLLファイルの使用
DLLファイル検証の検証用ファイル※に入っているDLLはご自由にご使用いただいて構いません。ただし、無許可での配布等はやめてください。連絡はこちら。 同梱の説明書
検証用ファイル:ダウンロード
同梱されているスクリプトファイルを用い、一度登録すると、Excelからいつでも数独を解析する関数を呼び出すことができます(用途は限定されていますが。。。)。
※ダウンロード時に警告がでるかもしれないが問題ない。
Excelマクロ管理ツール