Короткая версия есть в названии.
Длинная версия:
Я работаю над программой для научной оптимизации с использованием Java. Рабочая нагрузка программы может быть разделена на параллельную и последовательную фазы - параллельные фазы, что означает, что выполняется высокопараллельная работа. Чтобы ускорить программу (она работает часами / днями), я создаю количество потоков, равное количеству ядер ЦП на машине, которую я использую - обычно 4 или 8 - и делю работу между ними. Затем я запускаю эти потоки и присоединяюсь к ним, прежде чем перейти к последовательной фазе.
Пока все хорошо. Что меня беспокоит, так это то, что загрузка ЦП и ускорение параллельных фаз не приближаются к «теоретическому максимуму» - например, если у меня 4 ядра, я ожидаю увидеть «загрузку» где-то между 350-400% (как сообщается сверху), но вместо этого он колеблется между 180 и 310. Используя только один поток, я получаю 100% загрузку ЦП.
Единственные известные мне причины, по которым потоки не работают на полной скорости:
блокировка из-за ввода / вывода
-блокировка из-за синхронизации
Никаких операций ввода-вывода в моих параллельных потоках и синхронизации не происходит - единственные структуры данных, общие для потоков, доступны только для чтения и являются либо базовыми типами, либо (не параллельными) коллекциями. Поэтому я ищу другие объяснения. Возможно, что несколько потоков неоднократно блокируются для сбора мусора, но это может иметь смысл только в ситуации с нехваткой памяти, и я выделяю намного больше требуемого максимального пространства кучи.
Любые предложения будут оценены.
Обновление: На всякий случай, если кому-то интересно, после еще одного исследования я настроил код для общей производительности и вижу лучшее использование, даже если я ничего не изменил в связи с синхронизацией. Однако некоторые изменения должны были привести к меньшему количеству новых выделений кучи, в частности, я избавился от некоторого использования итераторов и временных коробочных чисел (библиотека CERN "Colt" для производительность Java-вычислений была здесь полезна: она предоставляет коллекции, такие как IntArrayList, DoubleArrayList и т. д. для базовых типов.) Поэтому я думаю, что сборщик мусора был, вероятно, виновником.