ほとんどの条件下で、ローカル読み取りで問題なく動作するロックフリー コードをいくつか書きました。
メモリ読み取りでのローカル スピンは、スピン読み取りの前に常にメモリ バリアを挿入する必要があることを意味しますか?
(これを検証するために、特定の非常に特定の条件下で、リーダーが書き込まれた値をまったく見ないという結果になるリーダー/ライターの組み合わせを作成することに成功しました。ループ内で実行されるため、矢印はその方向を指していますが、メモリバリアを通過するコストについては完全にはわかりません.)
キャッシュのストア バッファにフラッシュするものが何もない場合、メモリ バリアを介してスピンするコストはいくらですか? つまり、すべてのプロセスが (C で) 行っているのは、
while ( 1 ) {
__sync_synchronize();
v = value;
if ( v != 0 ) {
... something ...
}
}
それは無料であり、メモリバスにトラフィックを邪魔しないと仮定するのは正しいですか?
別の言い方をすれば、次のように質問することです: メモリ バリアは、ストア バッファーをフラッシュし、無効化を適用し、コンパイラーがその場所全体で読み取り/書き込みを並べ替えないようにする以上のことを行いますか?
逆アセンブルすると、__sync_synchronize() は次のように変換されます。
lock orl
Intelのマニュアルから(同様に、初心者にとっては漠然としています):
Volume 3A: System Programming Guide, Part 1 -- 8.1.2
Bus Locking
Intel 64 and IA-32 processors provide a LOCK# signal that
is asserted automatically during certain critical memory
operations to lock the system bus or equivalent link.
While this output signal is asserted, requests from other
processors or bus agents for control of the bus are
blocked.
[...]
For the P6 and more recent processor families, if the
memory area being accessed is cached internally in the
processor, the LOCK# signal is generally not asserted;
instead, locking is only applied to the processor’s caches
(see Section 8.1.4, “Effects of a LOCK Operation on
Internal Processor Caches”).
私の翻訳: 「ロックと言うと、これはコストがかかりますが、必要な場合にのみ行っています。」
@BlankXavier:
ライターがストア バッファーから書き込みを明示的にプッシュアウトせず、それがその CPU で実行されている唯一のプロセスである場合、リーダーはライターの効果を確認できない可能性があることをテストしました (テスト プログラムで再現できますが、上で述べたように、特定のコンパイルオプションと専用のコア割り当てを使用した特定のテストでのみ発生します-私のアルゴリズムは正常に機能します。将来の問題)。
デフォルトでは、単純な書き込みはWB書き込み(ライトバック)であると思います。つまり、すぐにはフラッシュされませんが、読み取りは最新の値になります(「ストア転送」と呼ばれると思います)。そこで、ライタには CAS 命令を使用します。Intelのマニュアルで、これらすべての異なるタイプの書き込み実装(UC、WC、WT、WB、WP)、Intel vol 3A chap 11-10を発見し、まだそれらについて学んでいます。
私の不確実性は読者の側にあります.McKenneyの論文から、バスからキャッシュへの受信無効化のキューである無効化キューもあることがわかりました。この部分がどのように機能するかわかりません。特に、通常の読み取りをループする(つまり、ロックされていない、バリアなしで、揮発性を使用して、コンパイル後にオプティマイザーが読み取りを確実に残すようにする)と、毎回「無効化キュー」にチェックインすることを暗示しているようです。 (そのようなものが存在する場合)。単純な読み取りでは不十分な場合 (つまり、キューに入れられた無効化が保留されている間はまだ有効に見える古いキャッシュ ラインを読み取ることができます (これは私にも少し矛盾しているように聞こえますが、無効化キューはどのように機能するのでしょうか?))、アトミック読み取りは次のようになります。私の質問は次のとおりです。この場合、これはバスに影響を与えますか? (多分無いと思います。)
私はまだ Intel のマニュアルを読んでいますが、ストア フォワーディングについては素晴らしい議論が見られますが、無効化キューについては適切な議論が見つかりませんでした。C コードを ASM に変換して実験することにしました。これがどのように機能するかを実際に理解するには、これが最善の方法だと思います。