5

シングルスレッドの Java コードを使用してアルゴリズムを実装しました。JIT コンパイルを有効にしてプログラムを実行すると、マシンの 8 つのコアすべてが飽和状態になります。-XintJIT コンパイルを無効にする JVM オプションを使用して同じプログラムを実行すると、期待どおりにシングル コアで実行されます。

これは私のJavaバージョン情報です:

java version "1.7.0_25"
OpenJDK Runtime Environment (IcedTea 2.3.10) (7u25-2.3.10-1ubuntu0.12.10.2)
OpenJDK 64-Bit Server VM (build 23.7-b01, mixed mode)

コードが並列化されているように見えるのはなぜですか? HotSpot がいつコードを並列化できるかについての詳細情報はどこにありますか?

4

3 に答える 3

7

Java はコードを自動的に並列化しません。私の推測では、あなたが見ているコアの飽和は、コードをコンパイルする JIT であると思います。テスト プログラムの入力を大きくして実行時間を長くし (おそらく 2 ~ 3 分)、しばらくすると速度が低下するかどうかを確認します。

于 2013-10-03T16:31:20.690 に答える
2

コードを自動的に直接並列化するわけではありませんが、より多くのマシン リソースを使用してコードをより高速に実行します。実行時データに基づいて、プロファイリング、コンパイル、ガベージ コレクション、および継続的な再コンパイルを行っています。可能な限り、これらの操作は他の CPU で実行されます。

同じパラメーターを使用してメソッドを十分に呼び出して、そのパラメーターの結果を完全にインライン化すると判断するか、特定のメソッドのかなりの数の if ステートメントが取得されない場合はそれらを最適化し、異なる場合は元のステートメントになる可能性があります。パラメーター。これらの操作によってプログラムが遅くなったりブロックされたりすることを望まないため、異なるスレッドで実行します。

十分に長く実行した場合は、単一の CPU をいっぱいにすることに戻ることがわかります。

于 2013-10-03T16:36:18.487 に答える
1

上記の答えは、おおむね正しいです。写真を完成させるために答えているだけです。明らかに、JVM はユーザー コードを自動的に並列化せず、独自のスレッドが進行しています。これらのスレッドの数はさまざまですが、一般的に次のスレッドがあります。このスレッド スタックのスナップショットは、ホットスポット (OpenJDK) JVM のライブ フェーズの開始時に取得されます。ここでは、オクタコアまたはクアッドコア マシンのすべてのコアを簡単に占有できる 11 個のスレッドを確認できます。スレッド名もその目的を説明しています。

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff0160800 nid=0x2f91 runnable [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff0158800 nid=0x2f90 waiting on condition [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff0156000 nid=0x2f8f waiting on condition [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0153000 nid=0x2f8e waiting on condition [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0150800 nid=0x2f8d waiting on condition [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff014e800 nid=0x2f8c runnable [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0103800 nid=0x2f8b in Object.wait() [0x00007ffff412f000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff00fa000 nid=0x2f8a in Object.wait() [0x00007ffff4230000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0x2f86 runnable [0x00007ffff7fca000]

"VM Thread" os_prio=0 tid=0x00007ffff00ef800 nid=0x2f89 runnable 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff015f000 nid=0x2f92 waiting on condition 

同様に、次のスレッド スタックのスナップショットは、ガベージ コレクターが動作していることを示しています。このスナップは、GC 呼び出し後に取得されました。GC の並列実装を実行しているため、GC だけで 8 つのスレッドがあります (オクタコア マシンでテストしているため、GC スレッドはコアの数に等しいと思います)。

Full thread dump OpenJDK 64-Bit Server VM (25.71-b00-debug mixed mode):

"Service Thread" #9 daemon prio=9 os_prio=0 tid=0x00007ffff017e800 nid=0xaa1 runnable  (no locks) [0x0000000000000000]

"C1 CompilerThread3" #8 daemon prio=9 os_prio=0 tid=0x00007ffff016e800 nid=0xaa0 waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread2" #7 daemon prio=9 os_prio=0 tid=0x00007ffff016b800 nid=0xa9f waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007ffff0169800 nid=0xa9e waiting on condition  (no locks) [0x0000000000000000]

"C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007ffff0166000 nid=0xa9d waiting on condition  (no locks) [0x0000000000000000]

"Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007ffff0164800 nid=0xa9c runnable  (no locks) [0x0000000000000000]

"Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007ffff0119000 nid=0xa9b in Object.wait()  (no locks) [0x00007fffba33d000]

"Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007ffff0110000 nid=0xa9a in Object.wait()  (no locks) [0x00007fffba43e000]

"main" #1 prio=5 os_prio=0 tid=0x00007ffff000d000 nid=0xa8b runnable  (no locks) [0x00007ffff7fc9000]

"VM Thread" os_prio=0 tid=0x00007ffff0105000 nid=0xa99 runnable  (no locks) 

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007ffff0026800 nid=0xa91 runnable  (no locks) 

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007ffff0028800 nid=0xa92 runnable  (no locks) 

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007ffff002a800 nid=0xa93 runnable  (no locks) 

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007ffff002c800 nid=0xa94 runnable  (no locks) 

"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x00007ffff002e800 nid=0xa95 runnable  (no locks) 

"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x00007ffff0030800 nid=0xa96 runnable  (no locks) 

"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x00007ffff0032800 nid=0xa97 runnable  (no locks) 

"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x00007ffff0034800 nid=0xa98 runnable  (no locks) 

"VM Periodic Task Thread" os_prio=0 tid=0x00007ffff017f800 nid=0xaa2 waiting on condition  (no locks) 

結論

スレッドの数は実行時に変化し、多くのスレッドがオンザフライで生成されて強制終了されるため、実行時間に関係なく、Java プログラムが単一のコアを使用することはほとんどありません。

上記の出力は、GDB と openJDK の内部デバッグ API を使用して生成されました。これらのスレッドとその目的について詳しく知りたい場合は、次を参照してください: openJDK のスレッド管理

于 2017-01-12T08:02:18.153 に答える