みなさん、VBAの2次元配列への代入をループさせる時に、1次元・2次元どちらを外側のループにしますか?
というのも、下記サイトで配列へのアクセス高速化の方法(C言語です)が記載されており、興味を持ったので参考までにVBAで試してみたのですが、どうも結果が反対になるようなのです・・・
http://fast-programming.aglk.net/double-array/sa …
こちらのサイト内では、1次元を外側のループにしたほうが早い、という処理結果だと思いますが、
手元では反対になりました・・・
質問としては、
言語が異なると、配列へのアクセスもかわるのでしょうか?
それとも、私の記述がサイトのものと違っているのでしょうか?
下記内容も含め、気軽に回答していただけたら幸いです。
以下、ソースと結果です。
同じ内容で、①、②の部分だけ入れ替えて計測しました。
結果はコードのさらに下です。
'-------------------------------------------
Option Explicit
Declare Function GetTickCount Lib "kernel32" () As Long
Sub speedtest()
Dim i As Long, j As Long, cnt As Long
Dim st As Double, ft As Double
Dim table(1 To 1000, 1 To 1000)
Dim res As String
res = ""
For cnt = 1 To 10
st = GetTickCount()
For i = 1 To 1000
For j = 1 To 1000
table(i, j) = 1 ’・・・・①
' table(j, i) = 1 ’・・・・②
Next
Next
ft = GetTickCount() - st
res = res & cnt & " : " & ft & vbCrLf
Next
Debug.Print res
Erase table
End Sub
'-------------------------------------------
結果
<①>
1 : 62
2 : 63
3 : 78
4 : 62
5 : 63
6 : 78
7 : 62
8 : 62
9 : 63
10 : 78
<②>
1 : 31
2 : 47
3 : 31
4 : 31
5 : 31
6 : 47
7 : 31
8 : 31
9 : 32
10 : 46
No.3ベストアンサー
- 回答日時:
後出しで回答はほぼNo2と同じですが、言語仕様によってアクセスではなく(アクセスかな?)メモリの確保の仕方が異なります。
参考に、メモリをどう確保しているかを確認する手段の1つを。
値をただ取り出すだけならForEachがダントツで速いんですが、順番が決まっていたり
値をセットしていく場合はループをどう組むかは考える必要があります。
どのようにメモリを確保しているかが分かれば、出来るだけアドレスの移動が少ない順になるよう
組めば良し、確認方法が分かれば言語が変わっても最適なループロジックを組めるように
なるかもしれません。
Cではポインタが使えるので配列がどういう順でメモリに展開されているかがわかるかと思いますが、
VBAの場合、ポインタが一応使えません。
が、簡単な確認方法だけ以下に提示します。
' 64bit
Private Declare PtrSafe Function VarPtrArray Lib "VBE7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr
' 32bit(確認してない)
Private Declare Function VarPtrArray Lib "VBE7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr
配列の宣言した後なり、値入れた後なりに以下。
Debug.Print Hex(VarPtr(table(0, 0)))
Debug.Print Hex(VarPtr(table(1, 0)))
Debug.Print Hex(VarPtr(table(2, 0)))
Debug.Print Hex(VarPtr(table(3, 0)))
Debug.Print Hex(VarPtr(table(0, 0)))
Debug.Print Hex(VarPtr(table(0, 1)))
Debug.Print Hex(VarPtr(table(0, 2)))
Debug.Print Hex(VarPtr(table(0, 3)))
VarPtrは変数のアドレスを返す関数です。それを16進数にして表示
質問内容のコードでは、配列tableでは型を指定していないので分かりやすく4バイトのLongにすると
Dim table(1 to 1000, 1 to 1000) as Long
恐らく下記のような出力がされます。(Excelの起動し直しでアドレスは変わるが)
28B0040 ' table(1, 1)
28B0044 ' table(2, 1) 4byte増えてる
28B0048
28B004C
28B0040 ' table(1, 1)
28B0FE0 ' table(1, 2) 4000byte(0FA0)増えてる
28B1F80
28B2F20
Cと同じメモリ確保の仕方の言語が圧倒的だったり、Cから始めた人も多いせいか、
私もよく、arry[外,内]というようなループを作ってしまいます。
配列として確保し、配列として操作することが少なかったり、そこまで大きな配列を作らなかったりで
全然気にしない事も多いのですがこの質問で見直すべきだな、と改めて考えさせられました。
解り易い回答ありがとうございます。
こんな方法があるとは・・・
素人の私にとって、ただただ自分の無知を嘆くばかりです。
納得しました。
No.2
- 回答日時:
vba 多次元配列 メモリ配置
で検索したところ、いくつか見付かりましたが、いずれも
A(1,1) の「となり」はA(2,1) だというものです。
多次元配列の考え方は、言語や、(同じ言語での)使用ライブラリ等によって異ります。
VBAではA(X,Y,Z) という考え
C では A[Z][Y][X] という考えを採用した、と言えるでしょう。
回答ありがとうございます。
>A(1,1) の「となり」はA(2,1) だというものです。
>VBAではA(X,Y,Z) という考え
C では A[Z][Y][X] という考えを採用した、と言えるでしょう。
うーん、なるほど。
私はどうも、二次元配列をワークシートでイメージしており、
メモリの配置の話がちんぷんかんぷんでしたが、今回の件は良い勉強になりました。
No.1
- 回答日時:
一応確認だけど, カテゴリが Perl になってるのは認識してる?
さておき, そんなものは言語に依存する話だから「C でこうなっているから VBA でも同じだろう」などと安直に考えてはいけない.
もちろん「同じ言語ならどの処理系でも同じ」と言っていいかどうかも難しいところだ.
回答ありがとうございます。
>一応確認だけど, カテゴリが Perl になってるのは認識してる?
してません。カテゴリの存在を知りませんでした。
>さておき, そんなものは言語に依存する話だから「C でこうなっているから VBA でも同じだろう」などと安直に考えてはいけない.
その根拠を教えていただけまさんか?
>もちろん「同じ言語ならどの処理系でも同じ」と言っていいかどうかも難しいところだ.
そうですよね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
grepを利用して、特定の要素が...
-
配列へのプラス?
-
Dim flag(4) as boolean で配列...
-
チェックボックスのperlでの値...
-
エクセルVBAでTransposeの不思議
-
クラスに配列を渡す方法
-
Strawberry Perl for Windows ...
-
リストボックスに縦スクロール...
-
VBAのautofilter、criteriaの配...
-
perl 配列の要素数について
-
delphi の 標準偏差のプログラ...
-
Perl このプログラムの解説をお...
-
全組み合わせの出力プログラム
-
UWSCの終了の仕方
-
VBのReturnの使い方
-
Escキーを押すと、中断する時と...
-
VBA Dir関数でファイルをループ...
-
DoEventsが必要な理由について
-
アクティブセルから、A列最終行...
-
vb.netからエクセル関数書き込み
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
クラスに配列を渡す方法
-
エクセルVBAでTransposeの不思議
-
Excel VBA ユーザーフォームの...
-
VBAのautofilter、criteriaの配...
-
Strawberry Perl for Windows ...
-
二次元配列における要素数のは...
-
VB6で配列の最大値を簡単に求め...
-
リストボックスに縦スクロール...
-
文字の整列(printf)
-
ファイル名に日付・時刻を付与...
-
DataGridViewに配列の値を表示...
-
チェックボックスのperlでの値...
-
一致する要素が格納されている...
-
隣同士の数字を足し合わせる
-
perlで配列の要素が空なのを知...
-
条件に一致した塩基配列を含む...
-
perlで2次元配列をサブルーチ...
-
マクロ Publicでの配列定義
-
二次元配列のインデックスについて
-
perl 配列の要素数について
おすすめ情報