Оптимальное количество потоков на ядро

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

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

Есть ли возможность запуска параллелизуемого процесса для большего количества потоков, чем ядра? Другими словами, мой процесс завершится быстрее, медленнее или примерно за такое же количество времени, если я запустил его с использованием 4000 потоков вместо 4 потоков?

Ответ 1

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

Недавно я занимался тестированием производительности на двухъядерном процессоре, работающем на приложении ASP.NET на Mono, при довольно приличной нагрузке. Мы играли с минимальным и максимальным количеством потоков, и в итоге мы выяснили, что для этого конкретного приложения в этой конкретной конфигурации наилучшая пропускная способность была где-то между 36 и 40 потоками. Все, что за пределами этих границ, хуже. Урок выучен? Если бы я был вами, я бы тестировал с различным количеством потоков, пока не найду нужный номер для вашего приложения.

Одно можно сказать наверняка: потоки 4k займут больше времени. Это много контекстных переключателей.

Ответ 2

Я согласен с ответом @Gonzalo. У меня есть процесс, который не выполняет операции ввода-вывода, и вот что я нашел:

enter image description here

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

Машина 1.86 - это компьютер macbook с SSD. Другой mac - это iMac с обычным жестким диском (я думаю, это 7200 об/мин). У машины Windows также есть жесткий диск емкостью 7200 об/мин.

В этом тесте оптимальное число было равно числу ядер в машине.

Ответ 3

Я знаю, что этот вопрос довольно старый, но все сложилось с 2009 года.

Теперь нужно учитывать две вещи: количество ядер и количество потоков, которые могут выполняться в каждом ядре.

С процессорами Intel количество потоков определяется гиперпотоком, который составляет всего 2 (если доступно). Но Hyperthreading сокращает время выполнения на два, даже если не используется 2 потока! (т.е. один конвейер разделен между двумя процессами - это хорошо, когда у вас больше процессов, а не наоборот).

На других процессорах у вас может быть 2, 4 или даже 8 потока. Поэтому, если у вас есть 8 ядер, каждый из которых поддерживает 8 потоков, вы можете иметь 64 процесса, работающие параллельно без переключения контекста.

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

Из моего собственного опыта, если у вас много ввода-вывода, много потоков - это хорошо. Если у вас очень интенсивная работа с интенсивной памятью (прочитайте источник 1, прочитайте источник 2, быстро вычислите, напишите), то больше потоков не поможет. Опять же, это зависит от того, сколько данных вы читаете/записываете одновременно (т.е. Используете SSE 4.2 и читаете 256 битовых значений, что останавливает все потоки на своем шаге... другими словами, 1 поток, вероятно, намного проще реализовать и вероятно, почти так же быстро, если не на самом деле быстрее. Это будет зависеть от вашей архитектуры процесса и памяти, некоторые продвинутые серверы управляют отдельными диапазонами памяти для отдельных ядер, поэтому отдельные потоки будут быстрее, если ваши данные будут правильно поданы... вот почему, на некоторых архитектуры, 4 процесса будут работать быстрее, чем 1 процесс с 4 потоками.)

Ответ 4

Фактическая производительность будет зависеть от того, сколько добровольного урожая каждого потока будет сделано. Например, если потоки вообще не имеют ввода/вывода NO и не используют системные службы (т.е. Они связаны на 100% cpu), то 1 поток на ядро ​​является оптимальным. Если потоки выполняют все, что требует ожидания, вам придется поэкспериментировать, чтобы определить оптимальное количество потоков. 4000 потоков будет иметь значительные накладные расходы на планирование, поэтому, вероятно, тоже не оптимально.

Ответ 5

Ответ зависит от сложности алгоритмов, используемых в программе. Я придумал метод вычисления оптимального количества потоков, выполнив два измерения времени обработки Tn и Tm для двух произвольных чисел потоков n и m. Для линейных алгоритмов оптимальным числом потоков будет N = sqrt ((mn (Tm * (n-1) - Tn * (m-1)))/(nTn-mTm)).

Прочитайте мою статью относительно расчетов оптимального числа для различных алгоритмов: pavelkazenin.wordpress.com

Ответ 6

Я думал, что добавлю еще одну перспективу. Ответ зависит от того, принимает ли вопрос слабое масштабирование или сильное масштабирование.

Из Википедии:

Слабое масштабирование: как время решения зависит от количества процессоров для фиксированного размера проблемы на процессор.

Сильное масштабирование: как время решения зависит от количества процессоров для фиксированного общего размера проблемы.

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

Это справедливо даже тогда, когда число потоков превышает количество ядер. Например, предположим там 8 произвольных единиц (или AU) работы в программе, которые будут выполняться на 4-ядерном компьютере.

Случай 1: выполняется с четырьмя потоками, где каждый поток должен заполнять 2AU. Каждый поток занимает 10 секунд для завершения (с большим количеством промахов в кеше). С четырьмя ядрами общий объем времени будет составлять 10 с (10 с * 4 потока /4 ядра).

Случай 2: выполняется с восемью потоками, где каждый поток должен заполнять 1AU. Каждый поток занимает всего 2 секунды (вместо 5s из-за уменьшения количества промахов в кэше). С восемью ядрами общий объем времени составит 4 с (2 с * 8 потоков /4 ядра).

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

Ответ 7

4000 потоков за один раз довольно высоки.

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

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

Ответ 8

Benchmark.

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

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

Вы не можете знать, пока не проверите.

Ответ 9

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

Вы можете использовать man-страницу о команде "ps".

man ps

Если вы хотите рассчитать число всех пользователей, вы можете использовать одну из следующих команд:

  • ps -aux| wc -l
  • ps -eLf | wc -l

Расчет количества пользовательских процессов:

  • ps --User root | wc -l

Кроме того, вы можете использовать "htop" [Ссылка]:

Установка на Ubuntu или Debian:

sudo apt-get install htop

Установка на Redhat или CentOS:

yum install htop
dnf install htop      [On Fedora 22+ releases]

Если вы хотите скомпилировать htop из исходного кода, вы найдете здесь здесь.

Ответ 10

Один пример множества потоков ( "пул потоков" ) против одного на ядро ​​- это пример внедрения веб-сервера в Linux или Windows.

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

В Windows сервер будет реализован с использованием портов ввода-вывода IOC - IOCPs, которые приведут к запуску приложения: если завершение ввода-вывода ОС запускает резервный поток для его обработки. Когда обработка завершена (как правило, с другой операцией ввода-вывода, как в паре "запрос-ответ" ), поток возвращается в порт IOCP (очередь) для ожидания следующего завершения.

Если никакие операции ввода/вывода не завершены, обработка не выполняется, и нить не запускается.

Действительно, Microsoft рекомендует не более одного потока на ядро ​​в реализациях IOCP. Любые операции ввода-вывода могут быть присоединены к механизму IOCP. МОК также может быть отправлена ​​приложением, если это необходимо.

Ответ 11

Идеал - это 1 поток на ядро, если ни один из потоков не будет блокироваться.

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

Ответ 12

говоря о вычислении и связанной с памятью точке зрения (научные вычисления) потоки 4000 заставят приложение работать очень медленно. Частью проблемы является очень высокая накладная переключение контекста и, скорее всего, очень низкая локальность памяти.

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

Ответ 13

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