質問

どのような状況下で、2つの異なるスレッドがx86上の同じ配列の隣接する要素に同時に書き込むことは安全ではありませんか?非常識なメモリモデルを備えた一部のDS9Kのようなアーキテクチャでは、これがワードティアリングを引き起こす可能性があることを理解していますが、x86のシングルバイトはアドレス指定可能です。たとえば、Dプログラミング言語の real は、x86の80ビット浮動小数点型です。次のようなことをしても安全ですか?

real[] nums = new real[4];  // Assume new returns a 16-byte aligned block.
foreach(i; 0..4) {
    // Create a new thread and have it do stuff and 
    // write results to index i of nums.
}

注:これは安全であっても、キャッシュとの誤った共有の問題を引き起こし、パフォーマンスが低下する場合があることを知っています。ただし、私が念頭に置いているユースケースの場合、実際には問題にならない程度に書き込みはまれです。

編集:書き込まれた値を読み返す心配はありません。想定は、値が読み取られる前に同期が行われることです。私はこの方法でライティングの安全性のみに関心があります。

役に立ちましたか?

解決

x86には一貫したキャッシュがあります。キャッシュラインに書き込む最後のプロセッサがすべてを取得し、キャッシュに書き込みます。これにより、対応する値に書き込まれたシングルバイトと4バイトの値がアトミックに更新されます。

「安全」とは異なります。プロセッサがそれぞれ「所有」バイト/ DWORDSのみに書き込む場合そのプロセッサによって設計により、更新は正しくなります。実際には、あるプロセッサが他のプロセッサによって書き込まれた値を読み取るようにしたい場合、 同期。

また、「効率的」とは異なります。複数のプロセッサがそれぞれキャッシュラインの異なる場所に書き込むことができる場合、キャッシュラインはCPU間でピンポンする可能性があり、キャッシュラインが単一のCPUに移動してそこにとどまる場合よりもはるかに高価です。 通常のルールは、プロセッサ固有のデータを独自のキャッシュラインに配置することです。 もちろん、その1つの単語に1回だけ書き込みたい場合は、 キャッシュラインの移動と比較して作業量が重要な場合、 あなたのパフォーマンスは受け入れられます。

他のヒント

何かが足りないかもしれませんが、問題は予見できません。 x86アーキテクチャは必要なものだけを書き込み、指定された値以外の書き込みは行いません。キャッシュスヌーピングはキャッシュの問題を処理します。

x86の詳細について尋ねていますが、例は高水準言語です。 Dについてのあなたの特定の質問は、あなたが使用しているコンパイラ、またはおそらくD言語仕様を書いた人々によってのみ答えられます。たとえば、Javaでは、配列要素へのアクセスでティアリングが発生しないようにする必要があります。

x86について、操作の原子性は Intelソフトウェア開発者向けマニュアル第3巻のセクション8.1で指定されています。 。それによると、アトミックストア操作には、バイトの格納、すべてのx86 CPUでのワード境界整列ワードおよびdword境界整列dwordの格納が含まれます。また、P6以降のCPUでは、キャッシュライン内のキャッシュメモリへの16ビット、32ビット、および64ビットの非境界整列アクセスがアトミックであることも指定しています。

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