質問

masm32アセンブリを使用してメインメモリから読み取ろうとしていますが、これを行うために、(ここでの別の質問への回答で以前に推奨されているように)大きく分離されたメモリ位置を含む配列を作成しました(からの読み取りを避けるため)キャッシュ)。なんとか配列を作成して読み取れるようになりましたが、問題が発生しました。私がすでに実行してテストしたこの配列は、私が与えたデータを処理しています(つまり、数値)、すべてが機能します。しかし、記憶の場所が必要なのですが、それらへのマップや参照がどこにも見つかりません。つまり、次のようなものが必要です:

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

ただし、数値を使用する代わりに、対応するメモリ位置の予約語を使用する必要があります。しかし、私はそれらを見つけることができません =(、または他に何を探せばよいのかさえわかりません。


編集

正しく理解できたかどうかだけ確認させてください。その後、配列を使用する代わりに、間にスペースをすべて入れた変数を使用して、メイン メモリから強制的に読み取ることができると教えてください。

役に立ちましたか?

解決

あなたが言ったように、これは(連続した)バイトの配列です。

my_arr db 5, 2, 8, 9, 1, 7, 3, 0, 4, 6

これは 10 MB (CPU キャッシュに比べて大きい) を占有する変数です。

wasted_space BYTE 10485760 DUP(?)

以下に、間に多くの無駄なスペースがあるいくつかの変数を示します。

my_var_1 db 5
spacer_1 BYTE 10485760 DUP(?)
my_var_2 db 2
spacer_2 BYTE 10485760 DUP(?)
my_var_3 db 8
spacer_3 BYTE 10485760 DUP(?)
my_var_4 db 9
spacer_4 BYTE 10485760 DUP(?)
my_var_5 db 1
spacer_5 BYTE 10485760 DUP(?)
my_var_6 db 7
spacer_6 BYTE 10485760 DUP(?)
my_var_7 db 3
spacer_7 BYTE 10485760 DUP(?)
my_var_8 db 0
spacer_8 BYTE 10485760 DUP(?)
my_var_9 db 4
spacer_8 BYTE 10485760 DUP(?)
my_var_10 db 6

これ (データ セグメントに変数を作成する) は、データ メモリ アドレスを取得する 1 つの方法です (変数にはアドレスが含まれていません...)むしろ、変数はアドレスにあります)。

メモリ アドレスを取得するもう 1 つの方法は、O/S API を呼び出すことです。O/S API は、ヒープからメモリを割り当て、その割り当てられたメモリのアドレスを返します。たとえば、HeapAlloc API や VirtualAlloc API などです。


なぜ ASM でこれを行うのかわかりません (アセンブリを学ぶため以外)。キャッシュについて学ぶのであれば、C を使用しても同じように (そしてより簡単に) できると思います。

とにかく、私はキャッシュについて興味を持ちました。キャッシュミスを引き起こすにはどのくらいのスペースがあれば十分ですか?ミスを引き起こすには、いくつの異なる変数が必要でしょうか (キャッシュが分割されており、広い間隔で配置された複数の (ただし少数のみ) のメモリ キャッシュを含めることができるとすると)。

明らかに、それ(キャッシュ)は長年にわたって複雑なテーマになっています。 http://lwn.net/Articles/252125/ ウィキペディアからリンクされている記事です。この記事にはいくつかのグラフが含まれています。 図 3.11:複数のサイズのシーケンシャル読み取り.

他のヒント

アセンブリでの間接メモリ アクセス

配列内のバイトをメモリ アドレスとして扱うには、ベース アドレスとして機能するレジスタにバイトをロードし、そのレジスタが指すメモリにアクセスする必要があります。

MOV AX, [MY_ARR+3]  ; Element 3 in array, that is 9
MOV BX, [AX]        ; Read from that address

キャッシュについて

キャッシュは、この配列でカバーされるメモリ アドレスのスパンよりもはるかに大きい可能性が高いため、すべてがキャッシュに収まることに注意してください。

また、キャッシュが連想的である可能性が高いことも考慮してください。つまり、非常に離れたアドレスが同じ (完全な) キャッシュ ライン上にない場合でも、キャッシュに一緒に収まる可能性があります。

実際にキャッシュを使い果たし、メモリに直接アクセスする必要があることを保証するには、キャッシュよりも大きい一連の連続したメモリ位置に (ループで) アクセスする必要があります。つまり、キャッシュと同じ大きさの配列を作成します。また、おそらく複数のキャッシュ層 (L1、L2、場合によっては L3、そしてさらに) が存在することも考慮してください。そのため、どれくらいのサイズが必要かは、どのキャッシュをオーバーランさせたいかによって異なります。


私はかつてそのようなメモリとキャッシュへのアクセスの時間を計るプログラムを C で書き、統計計算と時間測定のオーバーヘッド (これほど短い時間スケールでは無視できません) の補正を行うことで、非常に正確な結果が得られました (これはおそらくテストをより長く実行し、標準偏差が低下するのを待つことで、必要なだけ正確になります)。

ただし、私のプログラムはそれを行うための最も効率的な方法ではなく、キャッシュの結合性についてもあまり示唆しませんでした (これはカラーリングスキームの知識を使って別途測定する必要があります)。ただし、両方とも、いくつかの考え抜かれたトリックを使用して、比較的アーキテクチャに依存しない方法でかなり効率的に実行されました。 SIGMETRICS 2005 年の Larry McVoy と Carl Staelin の成果.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top