29

これは複雑な質問です。答える前によく考えてください。

この状況を考えてみましょう。2 つのスレッド (リーダーとライター) が 1 つの global にアクセスしますint。これは安全ですか?普段なら何も考えずに答えます、はい!

しかし、ハーブ・サッターはそうは考えていないように私には思えます。効果的な並行性に関する彼の記事では、欠陥のあるロックフリー キュー修正されたバージョンについて説明しています。

最初の記事の最後と 2 番目の記事の最初で、彼はめったに考慮されない変数の特性である書き込み順序について説明しています。Int はアトミックで優れていますが、int は必ずしも順序付けられているわけではなく、上記のシナリオを含むロックフリー アルゴリズムを破壊する可能性があります。現在および将来のすべてのプラットフォームで正しいマルチスレッド動作を保証する唯一の方法は、アトミック (別名メモリ バリア) またはミューテックスを使用することであることに完全に同意します。

私の質問; 書き込みの再オーダリングは、実際のハードウェアで問題になることはありますか? それとも、マルチスレッドのパラノイアは衒学的なだけですか?
従来のユニプロセッサ システムはどうでしょうか。
組み込みの power-pc のような単純な RISC プロセッサはどうですか?

明確化: ハードウェア (プロセッサ/キャッシュ) の変数書き込みの並べ替えについて Sutter 氏が述べたことにもっと興味があります。オプティマイザがコンパイラ スイッチを使用してコードを壊したり、コンパイル後のアセンブリを手作業で検査したりするのを防ぐことができます。ただし、ハードウェアが実際にコードを台無しにする可能性があるかどうかを知りたいです。

4

9 に答える 9

26

アセンブリを検査するというあなたの考えは十分ではありません。並べ替えはハードウェア レベルで発生する可能性があります。

「これは読み取りハードウェアの問題ですか?」という質問に答えるには:はい! 実際、私は自分自身でその問題に遭遇しました。

ユニプロセッサ システムやその他の特殊な状況で問題を回避しても問題ありませんか? 私は「いいえ」と主張します。なぜなら、今から 5 年後にはマルチコアで実行する必要があり、これらすべての場所を見つけるのは難しい (不可能ですか?) からです。

1 つの例外: 実際にハードウェアを完全に制御できる組み込みハードウェア アプリケーション用に設計されたソフトウェア。実際、ARMプロセッサなどの状況で、私はこのように「だまされた」ことがあります。

于 2009-01-03T19:59:07.433 に答える
9

うん - メモリバリアを使用して、必要に応じて命令の並べ替えを防ぎます。一部の C++ コンパイラでは、すべての読み取りと書き込みに対して暗黙的なメモリ バリアを挿入するように volatile キーワードが拡張されていますが、これは移植可能なソリューションではありません。(Interlocked* win32 API と同様)。Vista では、読み取りまたは書き込みのセマンティクスを指定できる、より粒度の細かい新しい Interlocked API もいくつか追加されています。

残念ながら、C++ のメモリ モデルは非常に緩いため、このようなコードはある程度移植できず、プラットフォームごとに異なるバージョンを作成する必要があります。

于 2009-01-03T19:56:55.470 に答える
5

あなたが言ったように、キャッシュまたはプロセッサレベルで並べ替えが行われるため、特にマルチプロセッサ(特に非x86プラットフォーム)の場合、適切な同期を確保するために実際にはある種のメモリバリアが必要です。(私はシングル プロセッサ システムにはこれらの問題がないと信じていますが、これについて私を引用しないでください。

于 2009-01-03T19:51:13.547 に答える
5

命令の並べ替えが x86/x64 より積極的な Itanium プロセッサではありますが、この問題に遭遇しました。

(当時は) 代入後の書き込みバリア以外にコンパイラに指示する方法がなかったため、修正はインターロック命令を使用することでした。

これをきれいに処理するには、言語拡張が本当に必要です。volatile の使用 (コンパイラでサポートされている場合) は、コードの一部からできるだけ多くのパフォーマンスを絞り出そうとする場合には粗すぎます。

于 2009-01-03T20:16:50.627 に答える
4

これは実際のハードウェアで問題になることはありますか?

もちろん、特に現在および将来の CPU が複数のコアに移行している現在では。アプリケーションに機能を実装するために順序付けられた原子性に依存しており、選択したプラットフォームまたは同期プリミティブの使用を介してこの要件を保証できない場合、すべての条件下で、つまり顧客がシングルコア CPU からマルチコア CPU に移行する場合、問題が発生するのを待っているだけです。

参照された Herb Sutter の記事 (2 つ目) からの引用

順序付けられたアトミック変数は、一般的なプラットフォームや環境ではさまざまな方法で綴られています。例えば:

  • volatileのように、C#/.NET でvolatile int
  • volatileまたは Java では * Atomic* で、volatile int, AtomicInteger.
  • atomic<T>次の ISO C++ 標準である C++0x では、atomic<int>.

C++0x が順序付けられた原子性を実装する方法を見ていないので、今後の言語機能が純粋なライブラリの実装なのか、それとも言語の変更に依存するのかを特定することはできません。提案を見直して、新しい標準が利用可能になるまで、現在のツール チェーンに非標準の拡張として組み込むことができるかどうかを確認できます。状況によっては、既に利用できる場合もあります。

于 2009-01-03T20:16:37.397 に答える
3

これは実際のハードウェアの問題です。私の友人は IBM で働いており、主に顧客のコードにあるこの種の問題を突き止めることで生計を立てています。

悪いことがどのように発生するかを知りたい場合は、Java メモリ モデル (および現在は C++ メモリ モデル) に関する学術論文を検索してください。実際のハードウェアで可能な並べ替えを考えると、高級言語で何が安全かを理解しようとするのは悪夢です。

于 2009-01-03T20:08:40.360 に答える
2

いいえ、これは安全ではなく、この問題を示す実際のハードウェアがあります。たとえば、xbox 360 の powerpc チップのメモリ モデルでは、書き込みの順序を変更できます。これは、組み込み関数に障壁がないために悪化します。詳細については、 msdnに関するこの記事を参照してください。

于 2010-10-17T05:03:05.363 に答える
1

質問をしたとき、私が最も興味を持ったのはユニプロセッサのpowerpcでした。コメントの 1 つで、InSciTek Jeffは powerpc SYNC および ISYNC 命令について言及しました。決定的な答えへの鍵となるもの。IBMのサイトで見つけました

記事は大きくてかなり密集していますが、テイクアウトは安全ではありません。古い powerpc のメモリ オプティマイザは、ユニプロセッサで問題を引き起こすほど洗練されていません。ただし、新しいものははるかに積極的であり、グローバル int への単純なアクセスさえも中断する可能性があります。

于 2009-01-05T16:09:36.660 に答える
1

「それは安全ですか」という質問に対する答えは本質的にあいまいです。

コンピューターが発火しないという意味で、ダブルスであっても常に安全です。int が過去のある時点で保持していた値を常に取得するという意味では安全です。別のスレッドによって更新される/更新される値を取得する可能性があるという意味では、安全ではありません。

「アトミック」とは、2 番目の保証が得られることを意味します。double は通常アトミックではないため、32 個の古いビットと 32 個の新しいビットを取得できます。それは明らかに安全ではありません。

于 2009-01-05T09:55:04.453 に答える