Рекомендуемый размер пула потоков, в котором несколько связанных задач передаются один раз - PullRequest
3 голосов
/ 03 июня 2019

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

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

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

Для контекста, программа, над которой я работаю, работает с коллекциями матриц (представленных трехмерными массивами), где каждая матрица может содержать до 1000x1000 элементов.Одной из задач может быть выполнение операции свертки, и каждая задача является операцией над одной из матриц в коллекции.

Есть ли рекомендации для этого конкретного типа проблемы?

Ответы [ 2 ]

2 голосов
/ 03 июня 2019

То же, что вы слышите, когда этот вопрос задается для сервера: не делайте предположений , проводите экспериментов .

Попытайтесь определить (наихудший случай: угадать) типичную настройку оборудования, на которой ваши пользователи работают с вашим программным обеспечением. Затем убедитесь, что вы можете выполнять качественно автоматизированное тестирование производительности. А потом посмотри, что произойдет.

Но дело в том, что это мало поможет. Видите ли, когда вы запускаете свой собственный сервер, вы (надеюсь) контролируете рабочую нагрузку, с которой работают эти машины. Для настольной установки, где удаленные пользователи запускают ваш код на своих компьютерах ... у вас есть ноль понимание того, что еще работает там. Вы можете обнаружить, что 16 потоков подходят для 50% пользователей. Но остальные, возможно, делают много других вещей на своих машинах, а 16 уже слишком много для них.

И это настоящая суть. Независимо от того, какое число вы считаете «подходящим» для конкретной конфигурации оборудования, вы не можете контролировать другие рабочие нагрузки.

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

Кроме того, что может быть действительно полезным здесь: добавьте своего рода «сбор данных» в ваше приложение. Значение: регулярно звонить домой, чтобы сказать вам такие вещи, как: «это оборудование, на котором я работаю, я использую потоки X, а другая рабочая нагрузка в системе - Y». Это может помочь вам перейти к некоторой эвристике, чтобы адаптировать к наиболее важным настройкам пользователя. Но будьте внимательны к , какие данные собирать. Определите вопросы, на которые вы хотите получить предварительный ответ, а затем извлеките данные, необходимые для ответа на эти вопросы.

0 голосов
/ 03 июня 2019

Если ваша рабочая нагрузка требует значительных вычислительных ресурсов (привязана к ЦП), вы можете посмотреть ForkJoinPool, в котором реализовано кража рабочего .

A ForkJoinPoolотличается от других видов ExecutorService в основном тем, что использует воровство работы: все потоки в пуле пытаются найти и выполнить задачи, переданные в пул и / или созданные другими активными задачами (в конечном итоге блокирующие ожидание работы, если их нет).Это обеспечивает эффективную обработку, когда большинство задач порождают другие подзадачи (как и большинство ForkJoinTasks), а также когда много небольших задач передаются в пул от внешних клиентов.

...