Как ответил @axtavt, ожидание может быть проблемой. Вы должны сначала это исправить, так как это часть ответа, но не все. Это не поможет в вашем случае (на Q6600), потому что он кажется узким местом на 2 ядрах по какой-то причине, так что другой доступен для цикла занятости и поэтому нет никакого очевидного замедления, но на моем Core i5 это заметно ускоряет 4-х поточную версию.
Я подозреваю, что в случае Q6600 ваше конкретное приложение ограничено объемом доступного общего кэша или чем-то еще, специфичным для архитектуры этого ЦП. Q6600 имеет два 4-мегабайтных кэша L2, что означает, что процессоры используют их совместно, и кеш-памяти третьего уровня нет. На моем ядре i5 каждый ЦП имеет выделенный кэш L2 (256 КБ, а затем более широкий 8 МБ общий кэш L3. 256 КБ на каждый ЦП может иметь значение ... в противном случае это делает другая архитектура).
Вот сравнение Q6600 с вашим Collatz.java и Core i5 750.
На моем рабочем ПК, который также является Q6600 @ 2,4 ГГц, как ваш, но с 6 ГБ ОЗУ, Windows 7 64-битной и JDK 1.6.0_21 * (64-битной), вот некоторые основные результаты:
- 10000000 500000 1 (среднее из трех прогонов): 36982 мс
- 10000000 500000 4 (среднее из трех прогонов): 21252 мс
Конечно, быстрее - но не завершается в четверть времени, как вы ожидаете, или даже наполовину ... (хотя это примерно чуть больше половины, об этом чуть позже). Обратите внимание, что в моем случае я сократил размер рабочих блоков вдвое, а максимальная куча по умолчанию составляет 1500 м.
Дома у меня на Core i5 750 (4 ядра без гиперпоточности), 4 ГБ ОЗУ, 64-битная Windows 7, jdk 1.6.0_22 (64-битная):
- 10000000 500000 1 (среднее из 3 прогонов) 32677 мс
- 10000000 500000 4 (в среднем 3 пробега) 8825 мс
- 10000000 500000 4 (среднее из 3 запусков) 11475 мс (без исправления ожидания занятости, для справки)
версия с 4 потоками занимает 27% времени, которое занимает версия с 1 потоком, когда цикл занятости занят. Намного лучше. Очевидно, что код может эффективно использовать 4 ядра ...
- ПРИМЕЧАНИЕ. Java 1.6.0_18 и более поздние изменили настройки кучи по умолчанию, поэтому размер кучи по умолчанию на моем рабочем компьютере составляет почти 1500 м, а на домашнем ПК - около 1000 м.
Возможно, вы захотите увеличить кучу по умолчанию, на случай, если произойдет сборка мусора и немного замедлит работу вашей 4-поточной версии. Это может помочь, а может и нет.
По крайней мере, в вашем примере, есть вероятность, что ваш больший размер рабочей единицы слегка искажает ваши результаты ... вдвое это может помочь вам приблизиться по крайней мере к 2-кратной скорости, так как 4 потока будут заняты в течение большей части время. Я не думаю, что Q6600 будет лучше справляться с этой конкретной задачей ... будь то кеш или какая-то другая внутренняя архитектура.
Во всех случаях я просто запускаю "java Collatz 10000000 500000 X", где x = число указанных потоков.
Единственные изменения, которые я сделал в вашем java-файле, заключались в том, чтобы сделать один из отпечатков в распечатке, чтобы было меньше разрывов строк для моих прогонов с 500000 на единицу работы, чтобы я мог видеть больше результатов в консоли одновременно, и я отменил цикл ожидания занятости, который важен для i5 750, но не имеет значения для Q6600.