7

Java言語では、再順序付けによってコードのセマンティクスに違いがない限り、コンパイルされたコードの行をコンパイラーが再配置できることはよく知られています。ただし、コンパイラは、現在のスレッドから見たセマティックについてのみ気にする必要があります。この並べ替えがマルチスレッドの状況でセマンティクスに影響を与える場合、通常は同時実行の問題が発生します(メモリの可視性)。

私の質問:

  1. このfreedmをコンパイラに許可することで何が達成されますか?コードを再配置することで、コンパイラーがより効率的なコードを生成することは本当に可能ですか?私はこれについての実際的な事例をまだ見ていません。これがもたらす可能性のある並行性のリスクが、利益をはるかに上回っていると感じることがあります。

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

4

3 に答える 3

8

javacコンパイラーは、ほとんど最適化を実行していません。

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

このfreedmをコンパイラに許可することで何が達成されますか?

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

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

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

はい。ただし、CPUによって行われる並べ替えの方が重要です。

私はこれについての実際的な事例をまだ見ていません。これがもたらす可能性のある並行性のリスクが、利益をはるかに上回っていると感じることがあります。

プログラマーがコンパイラーにこのような行を再配置しないように指示できる方法はありますか?

volatileこれが、、synchronizedブロック、などのメモリバリアを使用する理由ですLock。これらを使用すると、スレッドセーフが保証されます。

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

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

更新の並べ替えを回避することは、スレッドセーフの問題のごく一部です(最大の問題は、あいまいで、めったに発生しないため、テストが困難になることです)。スレッドセーフコードを作成すると、これは軽減されます。

于 2012-01-05T12:22:20.197 に答える
2

バイトコードを再配置するプロセスは、JIT(Just in Timeコンパイラ)によって管理されます。次のオプションを使用して、実行を停止できます。

-Djava.compiler=NONE

詳細はこちら:http ://www.cs.swarthmore.edu/~newhall/unixhelp/debuggingtips_Java.html

于 2012-01-05T12:21:24.887 に答える
2

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

そうそうです!

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

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

注:ここでは、大幅な高速化について話しています。おそらく3〜5倍の高速化です。

どれだけの量を把握したい場合は、インスタンス変数を多用するアプリケーションを使用して、すべてのインスタンス変数がになるように書き直してvolatileください。(これにより、並べ替えの範囲が狭まり、すべての読み取りと書き込みがメモリに送られます。)次に、元のアプリケーションのパフォーマンスを変更されたバージョンと比較してベンチマークします。

于 2012-01-05T12:56:11.470 に答える