2012-01-05 8 views
7

Java言語は、再順序付けによってコードの意味に違いがない限り、コンパイラがコンパイルされたコードの行を再配置できることはよく知られています。しかし、コンパイラは、現在のスレッドから見たように、sematicsについてのみ気にする必要があります。Javaメモリモデル:コンパイラ再編成コード行

  1. コンパイラにこのFREEDMを可能にすることによって、何を達成している。この再注文は、マルチスレッド状況で意味論に影響を与える場合、それは通常、並行性の問題(メモリの可視性)

    私の質問(複数可)が原因?コンパイラがコードを再配置することでより効率的なコードを生成することは本当に可能ですか?私はまだこれについて実用的なケースを見ています。私は時々、これがもたらすことができる並行性のリスクよりはるかに大きな利点があると感じています。

  2. プログラマがこのような行を並べ替えないようにコンパイラに指示する方法はありますか?私は、同期プリミティブを使用することは効果的に並べ替えの副作用を処理することを知っていますが、これをオフにする直接的な方法(コンパイラオプション)があるかどうか尋ねていますか?

答えて

8

javacコンパイラが行いを持っていない最適化の隣にあります。

JITネイティブコンパイラは、メモリの順序付けに問題がある場合に命令を並べ替えることができます。しかし、CPUは、同じ効果を有する命令およびメモリ更新を再注文することもできる。

このフリーダムをコンパイラに許可すると、何が達成されますか?

主な利点は、コードの移植性です。より多くの保証を提供すればするほど、すべてのプラットフォームが実際にこれを実行することがより困難になります。

また、厳密な順序ではなく命令を実行できるようにすることで、パフォーマンスが大幅に向上します。

コンパイラがコードを再配置することによって効率的なコードを生成することは本当に可能ですか?

はい。 CPUによって行われた順序変更はより重要です。

私はまだこれについて実際のケースを見ていません。私は時々、これがもたらすことができる並行性のリスクよりはるかに大きな利点があると感じています。

このような行を並べ替えないようにプログラマーに指示する方法はありますか?

あなたがvolatile、​​ブロックとLockなどのメモリバリアを使用する理由です。これらを使用すると、スレッドの安全性が保証されます。

私は同期プリミティブを使用すると効果的に並べ替えの副作用を処理することを知っていますが、これをオフにする直接的な方法(コンパイラオプション)があるかどうか尋ねていますか?

あなたはJITをオフにすることができますが、ほとんどの並べ替えはCPUによって行われるため、あまり効果がありません。

更新プログラムの再注文を避けることは、スレッド安全性の問題のほんの一部です(その最大の問題はあいまいであり、テストが困難になることはまれです)。そして、スレッドセーフコードを作成すると、これが緩和されます。

2

バイトコードを再配置するプロセスは、JIT(Just in Timeコンパイラ)によって管理されます。あなたは、次のオプションを指定して実行しているからそれを止めることができます。

-Djava.compiler=NONE 

がここに詳細を参照してください。http://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html

+1

これでCPUの再注文手順が停止することはありません。 ;) –

+0

そして、あなたのプログラムは本当に遅くなります。だから、プロダクションでの使用に便利なオプションではありません。 – Jesper

2

コンパイラがコードを再配置して効率的なコードを生成することは本当に可能ですか?

ああそうです!

現代のコンピュータアーキテクチャにおける人生の事実の1つは、メモリが主なパフォーマンスボトルネックであるということです。 CPUは、レジスタを使用して命令を主メモリから読み書きできる時間よりも何倍も速く登録することができます。そのため、高性能チップには2または3レベルのメモリキャッシュが搭載されています。さらに、典型的なCPUはパイプライニングを使用して、複数の命令を同時に実行する処理を可能にする。

これらのプロパティを持つCPUのパフォーマンスを最大限に引き出すには、コンパイラ(およびCPU自体)が命令を並べ替えてメモリ帯域幅を最大限に活用し、パイプラインをフルに保つ必要があります。また、ネイティブコードでは、レジスタに保存された値(変数)を使用でき、メモリ書き込みがメインメモリに伝播するのを待つメモリバリア命令の使用を最小限に抑える必要があります。これらは、Javaメモリモデルが並べ替えを許可するため、(Javaの場合のみ)許可されます。

注:ここで重要な高速化については、おそらく3倍から5倍のスピードアップです。

インスタンス変数を大量に使用するアプリケーションを取り、すべてのインスタンス変数がvolatileになるように書き換えます。これにより、並べ替えの範囲が狭くなり、すべての読み取りと書き込みがメモリに移動します。次に、元のアプリケーションのパフォーマンスを修正バージョンと比較します。

関連する問題