unaligned/aligned direct memory accessに関するブログ投稿を書いているときに、説明に苦労する結果にたどり着きました: メモリ アクセスが最初の 4 バイトにアライメントされている場合、データ構造が L1 に収まると、パフォーマンスに測定可能な差が見られます。キャッシュ。場合によっては、他の場所の方が 20% 高速です。
この記事では、実験と方法についてさらに詳しく説明していますが、要約は次のとおりです。
- L1 に収まるメモリ ブロックを割り当てます (私のラップトップでは 32k、hwloc を使用し、CPU の仕様を確認してください)。ブロックをキャッシュライン サイズに合わせます (通常は 64b、ハードウェアを確認してください)。割り当ては事前に行われ、測定されません。
- メモリ ブロックを反復処理し、指定されたオフセットの各キャッシュラインに long (何らかの値) を書き込みます (オフセットが 8 の倍数でない場合は、事実上、アライメントされていない書き込みが発生します)。
- メモリ ブロックを反復処理し、同じオフセットから読み取り、値が期待どおりであることを確認します。
オフセットが 0 ~ 3 の場合、パフォーマンスに違いがあるのはなぜですか?
測定されたコードの本質(コメントのリクエストによる):
for (address = startingAddress; address < limit; address += CACHE_LINE_SIZE) {
Unsafe.putLong(address, value);
}
for (address = startingAddress; address < limit; address += CACHE_LINE_SIZE) {
if (Unsafe.getLong(address) != value)
throw new RuntimeException();
}
開始アドレスは、キャッシュ アラインメント + オフセットです。完全な実験はここで入手できます: