2

編集 - 私が尋ねた質問が長すぎると思うので、非常に具体的にしています。

質問: メモリ ロケーションが L1 キャッシュにあり、ダーティとマークされていない場合。値が X であるとします。同じ場所に X を書き込もうとするとどうなりますか? そのような書き込みが冗長であると判断してスキップする CPU はありますか?

たとえば、2 つの値を比較し、メイン メモリへの冗長な書き込みを破棄する最適化はありますか? 具体的には、主流のプロセッサはこれをどのように処理しますか? 値が 0 のような特別な値の場合はどうなりますか? 0 のような特別な値でもそのような最適化がない場合、理由はありますか?

動機: キャッシュに簡単に収まるバッファがあります。複数のスレッドが、それらの間でリサイクルすることにより、潜在的にそれを使用する可能性があります。各使用には、バッファー内のn 個の場所 (連続している必要はありません)への書き込みが含まれます。リサイクルとは、単にすべての値を 0 に設定することを意味します。リサイクルするたびに、サイズ n の場所はすでに 0 です。(直感的に) 非常に多くの冗長な書き戻しを回避することで、リサイクル プロセスが高速化されるように思われます。

分岐命令自体が不要なキャッシュ ミスを引き起こす可能性があるため (if (buf[i]) {...} )、コードでこれを実行しても意味がありません。

4

3 に答える 3

1

私はあなたが説明する最適化を行うプロセッサを知りません-値を変更しないクリーンなキャッシュラインへの書き込みを排除します-しかし、それは良い質問、良い考え、素晴らしい心が同じように考えることなどです。

私は大きな返事を書きました、そしてそれから私は思い出しました:これは文学では「サイレントストア」と呼ばれています。「無料のサイレントストア」、K。LepakおよびM Lipasti、UWisc、MICRO-33、2000を参照してください。

とにかく、私の返信では、実装の問題のいくつかを説明しました。

ちなみに、このようなトピックは、USEnetニュースグループcomp.archでよく議論されています。

私は自分のウィキ、 http://comp-arch.netにもそれらについて書いています

于 2012-03-18T06:58:48.300 に答える
1

提案されたハードウェアの最適化では、遅延は減少しません。最下位レベルでの操作を検討してください。

  1. その場所の古い値は、キャッシュからCPUにロードされます(すでにキャッシュにあると想定)。
  2. 古い値と新しい値が比較されます。
  3. 古い値と新しい値が異なる場合、新しい値がキャッシュに書き込まれます。それ以外の場合は無視されます。

ステップ1は、実際にはステップ2および3よりも時間がかかる場合があります。これは、ステップ1の古い値がCPUに取り込まれるまで、ステップ2および3を開始できないためです。ソフトウェアで実装した場合も同様です。

古い値をチェックせずに、単に新しい値をキャッシュに書き込むかどうかを検討してください。2つの理由から、実際には上記の3ステップのプロセスよりも高速です。まず、古い値を待つ必要はありません。次に、CPUは出力バッファで書き込み操作をスケジュールするだけです。ALUが他の処理を開始できる間、出力バッファはキャッシュ書き込みを同時に実行できます。

これまでのところ、関係するレイテンシは、キャッシュとメインメモリの間ではなく、CPUとキャッシュの間のレイテンシだけです。


現代のマイクロプロセッサでは、キャッシュがキャッシュラインに編成されているため、状況はより複雑になります。バイト値がキャッシュラインに書き込まれるとき、書き換えられないキャッシュラインの他の部分は古い値を保持する必要があるため、キャッシュライン全体をロードする必要があります。

http://blogs.amd.com/developer/tag/sse4a/

読む
  • キャッシュヒット:データはキャッシュラインからターゲットレジスタに読み取られます
  • キャッシュミス:データがメモリからキャッシュに移動され、ターゲットレジスタに読み込まれます
書く
  • キャッシュヒット:データがレジスタからキャッシュラインに移動されます
  • キャッシュミス:キャッシュラインがキャッシュにフェッチされ、レジスタからのデータがキャッシュラインに移動されます
于 2010-07-27T04:43:12.910 に答える
0

これは、コンピューター アーキテクチャに関する最初の質問に対する回答ではありませんが、あなたの目標に関連している可能性があります。

この説明では、すべての配列インデックスはゼロから始まります。


nがsizeよりもはるかに小さいと仮定すると、2 つの情報を保存するようにアルゴリズムを変更します。

  1. サイズの配列
  2. セット コンテナーをエミュレートするために使用されるnの配列とカウンター。重複する値が許可されています。

フルサイズ配列のインデックスkにゼロ以外の値が書き込まれるたびに、値kをセット コンテナーに挿入します。

フルサイズの配列をクリアする必要がある場合は、set コンテナー (特にkを含む) に格納されている各値を取得し、フルサイズの配列内の対応する各インデックスをゼロに設定します。


2 レベル ヒストグラムまたは基数ヒストグラムと呼ばれる同様の手法も使用できます。

次の 2 つの情報が格納されます。

  1. の配列size
  2. のブール配列でceil(size / M)Mは基数です。ceil天井関数です。

フルサイズ配列のインデックスkにゼロ以外の値が書き込まれるたびfloor(k / M)に、ブール配列の要素にマークを付ける必要があります。

としましょう、bool_array[j]マークされています。これは、フルサイズ配列のj*M~の範囲に対応します。(j+1)*M-1

フルサイズの配列をクリアする必要がある場合は、ブール配列をスキャンしてマークされた要素を探し、フルサイズの配列内の対応する範囲をクリアする必要があります。

于 2010-07-25T20:15:34.297 に答える