Ulrich Drepper のWhat Every Programmer Should Know About Memory pdf を読んでいます。パート 6 の冒頭にコード フラグメントがあります。
#include <emmintrin.h>
void setbytes(char *p, int c)
{
__m128i i = _mm_set_epi8(c, c, c, c,
c, c, c, c,
c, c, c, c,
c, c, c, c);
_mm_stream_si128((__m128i *)&p[0], i);
_mm_stream_si128((__m128i *)&p[16], i);
_mm_stream_si128((__m128i *)&p[32], i);
_mm_stream_si128((__m128i *)&p[48], i);
}
そのすぐ下にそのようなコメントがあります:
ポインター
p
が適切に配置されていると仮定すると、この関数を呼び出すと、アドレス指定されたキャッシュ ラインのすべてのバイトが に設定されますc
。書き込み結合ロジックは、生成された 4 つの movntdq 命令を確認し、最後の命令が実行された後にのみメモリの書き込みコマンドを発行します。要約すると、このコード シーケンスは、キャッシュ ラインが書き込まれる前に読み取られることを回避するだけでなく、すぐには必要とされない可能性のあるデータでキャッシュが汚染されることも回避します。
私を悩ませているのは、関数へのコメントで「アドレス指定されたキャッシュラインのすべてのバイトを c に設定する」と書かれていることですが、ストリーム組み込み関数について理解していることから、キャッシュをバイパスします-キャッシュの読み取りもキャッシュの書き込みもありません。このコードはキャッシュ ラインにどのようにアクセスしますか? 2 番目の太字の部分は、関数が「キャッシュ ラインが書き込まれる前に読み取られるのを回避する」という、似たようなことを言っています。上記のように、キャッシュがいつどのように書き込まれるかはわかりません。また、キャッシュへの書き込みの前にキャッシュ書き込みを行う必要がありますか? 誰かが私にこの問題を明確にしてもらえますか?