私はJavaでマルチスレッドを扱っていますが、誰かが私に指摘したように、スレッドがウォームアップすることに気付きました。つまり、繰り返し実行されるとスレッドが速くなります。これが発生する理由と、それが Java 自体に関連するものなのか、それともすべてのマルチスレッド プログラムに共通する動作なのかを理解したいと思います。
それを例示するコード (Peter Lawrey による) は次のとおりです。
for (int i = 0; i < 20; i++) {
ExecutorService es = Executors.newFixedThreadPool(1);
final double[] d = new double[4 * 1024];
Arrays.fill(d, 1);
final double[] d2 = new double[4 * 1024];
es.submit(new Runnable() {
@Override
public void run() {
// nothing.
}
}).get();
long start = System.nanoTime();
es.submit(new Runnable() {
@Override
public void run() {
synchronized (d) {
System.arraycopy(d, 0, d2, 0, d.length);
}
}
});
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
// get a the values in d2.
for (double x : d2) ;
long time = System.nanoTime() - start;
System.out.printf("Time to pass %,d doubles to another thread and back was %,d ns.%n", d.length, time);
}
結果:
Time to pass 4,096 doubles to another thread and back was 1,098,045 ns.
Time to pass 4,096 doubles to another thread and back was 171,949 ns.
... deleted ...
Time to pass 4,096 doubles to another thread and back was 50,566 ns.
Time to pass 4,096 doubles to another thread and back was 49,937 ns.
つまり、より高速になり、約 50 ns で安定します。何故ですか?
このコードを実行し (20 回の繰り返し)、別の何かを実行し (前の結果の後処理と別のマルチスレッド ラウンドの準備をしましょう)、後で同じコードをさらに 20 回繰り返し実行するとRunnable
、ThreadPool
既にウォームアップされます。どのような場合ですか?
私のプログラムでは、Runnable
1 つのスレッド (実際には私が持っているプロセッシング コアごとに 1 つ、CPU を集中的に使用するプログラム) で実行し、次に他のシリアル処理を何度も交互に実行します。プログラムが進むにつれて速くなるようには見えません。温める方法が見つかるかもしれません…</p>