Сколько потоков я должен использовать в моей программе Java? - PullRequest
13 голосов
/ 25 сентября 2008

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

В коде он определяет константу;

//  number of threads
public static final int THREADS =  Runtime.getRuntime().availableProcessors();

Который затем устанавливает количество потоков, используемых для создания изображения.

Я понимаю его рассуждение о том, что количество потоков не может быть больше количества доступных процессоров, поэтому установите его на величину, позволяющую полностью использовать потенциал процессора (ов). Это правильно? или есть лучший способ использовать весь потенциал процессора (ов)?

РЕДАКТИРОВАТЬ: Чтобы дать больше разъяснений, конкретный алгоритм, который является потоком, масштабируется до разрешения создаваемого изображения (1 поток на пиксель). Это, очевидно, не лучшее решение, хотя. Работа, выполняемая этим алгоритмом, заключается в том, что она занимает все время и является исключительно математическими операциями, здесь нет блокировок или других факторов, которые могут привести к тому, что какой-либо конкретный поток будет спать. Я просто хочу максимально увеличить загрузку ЦП программ, чтобы сократить время их завершения.

Ответы [ 7 ]

15 голосов
/ 25 сентября 2008

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

Конфликт кеша является очень важным аспектом использования нескольких процессоров для обработки высокопараллельного алгоритма: убедитесь, что вы учитываете использование памяти. Если вы можете сконструировать свои объекты данных так, чтобы у каждого потока была своя собственная память, над которой он работает, вы можете значительно снизить конкуренцию в кэш-памяти между процессорами. Например, может быть проще иметь большой массив целых и иметь разные потоки, работающие над разными частями этого массива, но в Java проверки границ этого массива будут пытаться получить доступ к одному и тому же адресу в памяти, что может заставить данный ЦП перезагружать данные из кэша L2 или L3.

Разделение данных на собственные структуры данных и настройка этих структур данных таким образом, чтобы они были локальными по отношению к потокам (возможно, было бы даже более оптимальным использовать ThreadLocal - который фактически использует конструкции в ОС, которые обеспечивают гарантии того, что Процессор можно использовать для оптимизации кеша.

Лучший совет, который я могу вам дать - это тест, тест, тест. Не делайте предположений о том, как будут работать процессоры - в наши дни в процессорах происходит невероятное количество магии , часто с противоречивыми результатами. Также обратите внимание, что оптимизация среды выполнения JIT добавит дополнительный уровень сложности (возможно, хорошо, а может и нет).

10 голосов
/ 25 сентября 2008

С одной стороны, вы хотели бы подумать, что Threads == CPU / Cores имеет смысл. Зачем нужен поток, если его нечем запустить?

Деталь сводится к тому, «что делают потоки». Поток, который находится в режиме ожидания в ожидании сетевого пакета или дискового блока, тратит время процессора.

Если ваши потоки перегружены процессором, тогда имеет смысл соотношение 1: 1. Если у вас есть один поток «read the DB», который питает другие потоки, и один поток «Dump the data», который извлекает данные из потоков ЦП и создает выходные данные, эти два, скорее всего, могут легко разделить ЦП, в то время как процессор загружен. нити продолжают отрабатывать.

Реальный ответ, как и во всех видах вещей, это измерить его. Поскольку число настраивается (по-видимому), настройте его! Запустите его с потоками 1: 1 для процессоров, 2: 1, 1,5: 1 и т. Д. И оцените результаты. Быстро побеждает.

3 голосов
/ 25 сентября 2008

Номер, который нужен вашему приложению; не больше и не меньше.

Очевидно, что если вы пишете приложение, которое содержит какой-то параллельный алгоритм, то вы, вероятно, можете начать тестирование, чтобы найти хороший баланс в количестве потоков, но имейте в виду, что сотни потоков не будут ускорять какие-либо операции .

Если ваш алгоритм не может быть распараллелен, тогда никакие дополнительные потоки не помогут.

1 голос
/ 25 сентября 2008

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

Сначала подумайте о том, какие ресурсы доступны и что вы хотите оптимизировать (наименьшее время для завершения, наименьшее влияние на другие задачи и т. Д.). затем посчитай.

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

1 голос
/ 25 сентября 2008

Да, это совершенно разумный подход. Один поток на процессор / ядро ​​максимизирует вычислительную мощность и минимизирует переключение контекста. Я бы, вероятно, оставил это как есть, если бы не нашел проблему с помощью бенчмаркинга / профилирования.

Следует отметить, что JVM не гарантирует, что availableProcessors() будет постоянным, поэтому с технической точки зрения вы должны проверить это непосредственно перед порождением ваших потоков. Я сомневаюсь, что это значение может измениться во время выполнения на типичных компьютерах.

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

0 голосов
/ 25 сентября 2008

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

0 голосов
/ 25 сентября 2008

Преимущество использования потоков заключается в сокращении времени выполнения вашей программы на настенных часах, позволяя вашей программе работать над другой частью задания, в то время как другая часть ожидает, что что-то произойдет (обычно ввод / вывод). Если ваша программа полностью привязана к процессору, добавление потоков только замедлит ее. Если он полностью или частично связан с вводом / выводом, добавление потоков может помочь, но существует баланс между накладными расходами на добавление потоков и дополнительной работой, которая будет выполнена. Если количество потоков будет равно числу процессоров, это даст максимальную производительность, если программа полностью или почти полностью связана с процессором.

Как и во многих вопросах со словом «должен» в них, ответ: «Это зависит». Если вы считаете, что можете улучшить производительность, отрегулируйте количество потоков вверх или вниз и сравните производительность приложения. Также примите во внимание любые другие факторы, которые могут повлиять на решение (если ваше приложение потребляет 100% мощности компьютера, производительность других приложений будет снижена).

Это предполагает, что многопоточный код написан правильно и т. Д. Если бы у исходного разработчика был только один ЦП, у него никогда бы не было проблем с плохо написанным многопоточным кодом. Поэтому вам, вероятно, следует проверить поведение и производительность при настройке количества потоков.

Кстати, вы можете рассмотреть возможность настройки количества потоков во время выполнения вместо времени компиляции, чтобы упростить весь этот процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...