Что в действительности означает «разогревать» потоки при обработке многопоточности? - PullRequest
3 голосов
/ 04 марта 2011

Я имею дело с многопоточностью в Java, и, как кто-то указал мне, я заметил, что потоки нагреваются, они становятся быстрее, поскольку они многократно выполняются.Я хотел бы понять, почему это происходит и связано ли это с самой Java или является ли это обычным поведением каждой многопоточной программы.

Код (автор Питер Лоури), который иллюстрирует это, следующий:

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 нс.Почему это так?

Если я запускаю этот код (20 повторений), затем выполняю что-то еще (например, постобработку предыдущих результатов и подготовку к другому раунду многопоточности), а затем выполняю тот же Runnable для того жеThreadPool еще для 20 повторений, он будет уже подогрет, в любом случае?

В моей программе я выполняю Runnable только в одном потоке (фактически по одному на каждое ядро ​​обработки, этоПроцессор-интенсивная программа), затем некоторые другие последовательные обработки поочередно много раз.Похоже, программа не работает быстрее.Может быть, я смогу найти способ согреть его ...

Ответы [ 2 ]

9 голосов
/ 04 марта 2011

Нагревается не столько потоки, сколько JVM.

JVM имеет компиляцию JIT (Just In Time). Когда программа работает, она анализирует, что происходит в программе, и оптимизирует ее на лету. Он делает это, беря байт-код, который запускает JVM, и преобразовывая его в собственный код, который работает быстрее. Он может сделать это способом, оптимальным для вашей текущей ситуации, поскольку он делает это путем анализа фактического поведения во время выполнения. Это может (не всегда) привести к большой оптимизации. Даже больше, чем некоторые программы, которые скомпилированы в нативный код без таких знаний.

Вы можете прочитать немного больше на http://en.wikipedia.org/wiki/Just-in-time_compilation

Вы можете получить аналогичный эффект для любой программы, поскольку код загружается в кэш процессора, но я считаю, что это будет меньшей разницей.

1 голос
/ 04 марта 2011

Единственные причины, по которым я вижу, что выполнение потока может закончиться быстрее:

  • Менеджер памяти может повторно использовать уже выделенное пространство объекта (например, чтобы выделения кучи заполнялидоступная память до достижения максимального объема памяти - свойство Xmx)

  • Рабочий набор доступен в аппаратном кеше

  • Повторяющиеся операцииможет создавать операции, которые компилятор может упорядочить для оптимизации выполнения

...