2

スレッドAで更新され、他のスレッドで読み取られるメモリ変数があります。リーダーは、値がゼロ以外の場合にのみ気にします。値がインクリメントされると、ゼロに戻らないことが保証されています。以下のように最適化するのは理にかなっていますか?言い換えれば、読者側では、条件が満たされた後は「フェンス」は必要ありません。

std::atomic<int> counter;

writer:
increment()
{ 
    counter.store(counter+1, std:memory_order_release)
}

reader:
iszero()
{
    if (counter.load(std::memory_order_relaxed) > 0) return false;
    // memory fence only if condition not yet reached
    return (counter.load(std::memory_order_acquire) == 0);
}
4

1 に答える 1

2

まず、デフォルトの(逐次一貫性のある)アトミックを実際に使用しておらず、アプリのパフォーマンスを測定し、プロファイリングして、パフォーマンスの問題を引き起こしていることを確認した場合は、ここで戻ることをお勧めします。

ただし、本当にリラックスしたアトミックについて推論を開始する必要がある場合は...


x86でほぼ確実に機能しますが、期待どおりの動作が保証されるわけではありません。

他の非原子データの公開を保護するためにこれを使用していると思います。

その場合、リーダースレッドでゼロ以外の値を読み取った場合、ライターで行った非アトミックメモリ位置のさまざまな他の副作用(つまり、公開しているデータの初期化)を保証する必要があります。ストアの前のスレッドは、リーダースレッドに表示されます。

でゼロ以外を読み取るとストアと同期されstd::memory_order_relaxedないため、上記のコードにはこの保証がありません。std::memory_order_release

私が説明した動作を取得するには、を使用する必要がありますstd::memory_order_acquire。x86を使用している場合、acquireはメモリフェンス命令を生成しないため、パフォーマンスが異なる唯一の方法は、memory_order_relaxedコンパイラの最適化を防ぐことです。

于 2012-11-21T00:44:15.690 に答える