IntelやIBMのxlcなどのコンパイラは、データのプリフェッチ命令を自動的に挿入できます。
読みやすさを犠牲にしてプリフェッチに役立つコードがいくつかあります。つまり、次のようなコードの自然なグループ化があります
void foo(...){ // foo gets called frequently
...
char *myPtr = allocate(medium_size);
memset(myPtr,0,medium_size) // cache misses here. medium_size is ~ 1 cache line
// Miss occurs on first access by memset, but not enough
// data to ameliorate by any hardware prefetching
// triggered by memset. Basically foo() is called a lot
memsetによって発生するキャッシュミスのコストは、プロシージャ内で割り当てをさらに押し上げ、直後にプリフェッチ命令を発行することで軽減できます。その直後に、データを取り込むための十分な命令をmemsetとの間に配置します。キャッシュ。私の場合、medium_sizeを計算するコードは、プロシージャでさらに押し上げると少し面倒になり、読みにくくなります。
コンパイラがプリフェッチを価値のあるものにするためにコードを再スケジュールできれば(おそらくPGOのサポートにより)、両方の長所を活かすことができます。
これまでのところ、Visual Studioは組み込み関数、つまりプリフェッチ命令の手動配置のみをサポートしているようです。私が間違っている?
質問に応じた明確化の更新:
Q:コンパイラは上記のコードをどのように改善しますか?A:上記のコードは、関係するもののフレーバーを与えるためだけのものです。実際のコードはもっと複雑ですが、要約すると、割り当てとそれに格納されます。読み取りは、メモリに書き込むときにmemsetによって行われます。一部のアーキテクチャでは、これはキャッシュミスをトリガーしない場合がありますが、x86では明らかに(vTuneによると)トリガーします(以下のmarkgzが回答)。
Q:memsetを使用するだけで十分ではありませんか?memsetのメモリアクセスパターンは非常に予測可能であり、ハードウェアプリフェッチメカニズムがそれを処理する必要があります。A:はい、一般的にこれは真実であり、私は文脈の詳細を説明するという貧弱な仕事をしました。memsetを含むルーチン(foo)は非常に頻繁に呼び出され、キャッシュミスをトリガーするのはmemsetによる最初のメモリアクセスです。memsetがプリフェッチによってこのミスを改善するのに十分なデータがないため、memsetを呼び出す前にプリフェッチを行う必要があります。