17

Javaメモリモデルで私を悩ませているものがあります(すべてを正しく理解していても)。2 つのスレッド A と B がある場合、A と B の両方が同じモニターで同期しない限り、B が A によって書き込まれた値を参照できるという保証はありません。

スレッド間のキャッシュの一貫性を保証するシステム アーキテクチャでは、問題はありません。ただし、アーキテクチャがハードウェアのキャッシュ コヒーレンシをサポートしていない場合、これは基本的に、スレッドがモニターに入るたびに、以前に行われたすべてのメモリ変更をメイン メモリにコミットし、キャッシュを無効にする必要があることを意味します。そして、それは全体である必要がありますこれは、モニターが保護するメモリ内の変数に関する情報を持っていないためです。しかし、それは、頻繁に同期する必要があるアプリケーションのパフォーマンスに確実に影響を与えます (特に、実行時間の短いジョブを含むジョブ キューなど)。では、Java は、ハードウェア キャッシュ コヒーレンシのないアーキテクチャでも十分に機能するのでしょうか? そうでない場合、メモリ モデルが可視性についてより強力な保証をしないのはなぜですか? 言語がモニターによって保護されている情報を必要とする場合、より効率的ではないでしょうか?

ハードウェアでキャッシュの一貫性が保証されている場合でも、メモリ モデルは両方の世界で最悪の事態をもたらします。同期が絶対に必要であり、一方で、一貫性のないアーキテクチャ (フル キャッシュ フラッシュ) ではパフォーマンスが低下します。では、より厳密にする (モニターによって保護されている情報を要求する) べきではないか、潜在的なプラットフォームをキャッシュ コヒーレント アーキテクチャに制限するべきではないでしょうか?

今のままでは、あまり意味がありません。この特定のメモリ モデルが選択された理由を説明できる人はいますか?


編集:振り返ってみると、strictとloseの使用は悪い選択でした。保証が少ない場合に「厳密」を使用し、反対の場合に「失う」を使用しました。混乱を避けるために、より強いまたはより弱い保証の観点から話す方がおそらく良いでしょう.

4

4 に答える 4

6

ハードウェアでキャッシュコヒーレンシが保証されている場合でも、同期する絶対的な必要性

はい。ただし、プログラムが実行される特定のハードウェアアーキテクチャに対してではなく、Javaメモリモデルに対してのみ推論する必要があります。さらに、ハードウェアだけでなく、コンパイラとJIT自体が命令を並べ替えて、可視性の問題を引き起こす可能性があります。Javaの同期構造は、コード変換のすべての可能なレベル(コンパイラー/ JIT / CPU /キャッシュなど)で一貫して可視性とアトミック性に対応します。

一方、インコヒーレントアーキテクチャでのパフォーマンスの低下(フルキャッシュフラッシュ)

s / tを誤解したかもしれませんが、一貫性のないアーキテクチャでは、とにかくクリティカルセクションを同期する必要があります。そうしないと、並べ替えのためにあらゆる種類の競合状態に遭遇します。Javaメモリモデルが問題をさらに悪化させる理由がわかりません。

もっと厳しくすべきではありません(モニターによって保護されている情報が必要です)

キャッシュの特定の部分をフラッシュするようにCPUに指示することはまったく不可能だと思います。コンパイラが実行できる最善の方法は、メモリフェンスを解放し、キャッシュのどの部分をフラッシュする必要があるかをCPUに判断させることです。これは、私が推測するものよりもさらに粗いものです。よりきめ細かい制御が可能だとしても、並行プログラミングはさらに難しくなると思います(すでに十分に難しいです)。

AFAIK、Java 5 MM(.NET CLR MMと同様)は、x86やIA64などの一般的なアーキテクチャのメモリモデルよりも「厳密」です。したがって、それについての推論は比較的簡単になります。ただし、適用できるコンパイラ/ JIT / CPU /キャッシュの最適化が少なくなるため、パフォーマンスが大幅に低下するため、逐次一貫性に近いs/tを提供するべきではありません。

于 2010-06-16T15:06:39.277 に答える
5

既存のアーキテクチャはキャッシュの一貫性を保証しますが、シーケンシャルの一貫性は保証しません。2 つのことは異なります。シーケンシャル以来。一貫性は保証されません。一部の並べ替えはハードウェアによって許可されており、それらを制限するにはクリティカル セクションが必要です。クリティカル セクションは、あるスレッドが書き込む内容が別のスレッドから見えるようにする (つまり、データ競合を防ぐ) ことを保証し、従来の競合状態も防ぎます(2 つのスレッドが同じ変数をインクリメントする場合、スレッドごとに現在の変数の読み取りが必要です)。値と新しい値の書き込みは不可分です)。

さらに、実行モデルはあなたが説明したほど高価ではありません。キャッシュの一貫性はあるが、シーケンシャルな一貫性がないほとんどの既存のアーキテクチャでは、ロックを解放するときは、保留中の書き込みをメモリにフラッシュする必要があり、ロックを取得するときは、将来の読み取りで古い値が読み取られないようにするために何かを行う必要がある場合があります。ほとんどの場合、キャッシュの一貫性が維持されるため、読み取りが早すぎるのを防ぐことを意味します。ただし、読み取りはまだ移動してはなりません。

最後に、Java のメモリ モデル (JMM) は独特であると考えているようですが、基盤は現在かなり最先端であり、Ada、POSIX ロック (標準の解釈によって異なります)、および C に似ています。 /C++ メモリ モデル。JMM が既存のアーキテクチャーにどのように実装されているかを説明している JSR-133 クックブック ( http://g.oswego.edu/dl/jmm/cookbook.html ) を読むことをお勧めします。

于 2011-08-16T02:25:21.757 に答える
4

答えは、大規模な NUMA システムを含め、ほとんどのマルチプロセッサがキャッシュ コヒーレントであるということです。常に ccNUMA です。

キャッシュの一貫性が実際にどのように達成されるかについて、多少混乱していると思います。まず、キャッシュは、システム上の他のいくつかのものに関して一貫性がある場合と一貫性がない場合があります。

  • デバイス
  • (によって変更されたメモリ) DMA
  • データキャッシュと命令キャッシュ
  • 他のコア/プロセッサのキャッシュ (この質問に関するもの)
  • ...

一貫性を維持するには、何かを作成する必要があります。デバイスと DMA を使用する場合、DMA/デバイスに関して一貫性のないキャッシュを使用するアーキテクチャでは、キャッシュ (および場合によっては書き込みバッファー) をバイパスするか、DMA/デバイスに関連する操作でキャッシュを無効化/フラッシュします。

同様に、コードを動的に生成する場合、命令キャッシュをフラッシュする必要がある場合があります。

CPU キャッシュに関しては、MESI、MOESI などのコヒーレンシ プロトコルを使用してコヒーレンシが達成されます。これらのプロトコルは、特定のイベントに応答してキャッシュ間で送信されるメッセージを定義します (例: 非-exclusive キャッシュラインが変更された、...)。

これは (最終的な) コヒーレンシを維持するのに十分ですが、順序付けや、変更が他の CPU にすぐに表示されることを保証するものではありません。次に、書き込みを遅らせる書き込みバッファもあります。

そのため、各 CPU アーキテクチャは順序付けの保証 (たとえば、アラインされたストアの前のアクセスは、ストアの後で並べ替えることができない) を提供したり、そのような保証を要求する命令 (メモリ バリア/フェンス) を提供したりします。最終的に、モニターに出入りするためにキャッシュをフラッシュする必要はありませんが、書き込みバッファーを空にしたり、読み取りが終了するのを待って停止したりする可能性があります。

于 2011-06-14T21:34:50.597 に答える
1

JVM がアクセスできるキャッシュは、実際には単なる CPU レジスタです。それらの数は多くないため、モニターの終了時にそれらをフラッシュすることは大したことではありません。

EDIT:(一般に)メモリキャッシュはJVMの制御下にありません。JVMはこれらのキャッシュの読み取り/書き込み/フラッシュを選択できないため、この議論ではそれらについて忘れてください

各 CPU に 1,000,000 のレジスタがあると想像してください。JVM は喜んでそれらを利用して、非常に高速な計算を実行します。モニターの開始/終了に遭遇し、1,000,000 のレジスターを次のキャッシュ層にフラッシュする必要があります。

私たちがその世界に住んでいる場合、Java はどのオブジェクトが共有されていないか (大部分のオブジェクトは共有されていない) を分析できるほどスマートであるか、またはプログラマーにそのように依頼する必要があります。

Java メモリー・モデルは、平均的なプログラマーが問題なくマルチスレッド・アルゴリズムを作成できるようにする単純化されたプログラミング・モデルです。「簡略化された」とは、全世界で JLS の第 17 章を実際に読んで理解した人が 12 人いることを意味します。

于 2010-06-16T16:56:52.180 に答える