Как запрограммировать распределение потоков на многоядерных процессорах?

13

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

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

  1. Распределение потоков управляется операционной системой. Потоки создаются с помощью системных вызовов ОС, и, если процесс выполняется на многоядерном процессоре, ОС автоматически пытается распределить / запланировать разные потоки на разных ядрах.
  2. Распределение потоков управляется реализацией языка программирования. Распределение потоков между различными ядрами требует специальных системных вызовов, но стандартные библиотеки потоков языка программирования автоматически обрабатывают это, когда я использую стандартную реализацию потоков для этого языка.
  3. Распределение потоков должно быть запрограммировано явно. В моей программе я должен написать явный код, чтобы определить, сколько ядер доступно, и распределить разные потоки по разным ядрам, используя, например, библиотечные функции.

Чтобы конкретизировать вопрос, представьте, что я написал свое многопоточное приложение на Java или C ++ для Windows или Linux. Будет ли мое приложение волшебным образом видеть и использовать несколько ядер при работе на многоядерном процессоре (потому что все управляется операционной системой или стандартной библиотекой потоков), или мне придется изменить свой код, чтобы знать о нескольких ядрах? ?

Джорджио
источник

Ответы:

11

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

Простой ответ: Да, обычно он управляется операционной системой или библиотекой потоков.

Подсистема потоков в операционной системе будет назначать потоки процессорам в приоритетном порядке (ваш вариант 1). Другими словами, когда поток завершил выполнение для своего распределения времени или блоков, планировщик ищет следующий поток с наивысшим приоритетом и назначает его ЦПУ. Детали варьируются от операционной системы к операционной системе.

Тем не менее, существуют варианты 2 (управляемые языком программирования) и 3 (явно). Например, библиотека Tasks и async / await в последних версиях .Net предоставляют разработчику гораздо более простой способ написания распараллеливаемого кода (т.е. который может выполняться одновременно с самим собой). Функциональные языки программирования изначально параллелизуемы, и некоторые среды выполнения будут по возможности запускать разные части программы параллельно.

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

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

Актон
источник
Спасибо за объяснение (+1). Моя тестовая программа представляет собой реализацию сортировки слиянием. В фазе разделения я хочу создавать разные потоки, пока есть доступные ядра. Например, с двумя ядрами каждая половина массива будет отсортирована другим потоком / ядром. Во время слияния лишние нити затем соединяются / завершаются.
Джорджио
Таким образом, сложно распараллелить сортировку, если данные распределены случайным образом. Да, вы можете разбить его на части, а затем отсортировать каждую часть в отдельном потоке, но в любом случае вам все равно придется объединить все части вместе. Если потоки совместно используют структуры данных, вы также можете столкнуться с проблемами конкуренции или блокировки. Я не говорю, что сортировка не может извлечь выгоду из многопоточности, но это не будет линейным улучшением производительности.
Актон
Две половины массива могут быть отсортированы независимо, потому что данные не передаются. Только первое разделение и последнее объединение должны быть выполнены одним потоком, управляющим целым массивом или списком, содержащим данные. Это означает, что одно полное сканирование данных не может быть выполнено параллельно; могут все остальные сканы.
Джорджио
Конечно, я также считаю ваши примеры хорошими кандидатами. Сейчас я просто более знаком с сортировкой слиянием (и я реализовал ее непараллельную версию), что (возможно) сделает сортировку слиянием более подходящей для меня в качестве первой попытки.
Джорджио
2
Я хотел бы добавить к этому ответу, что хорошие операционные системы достаточно умны, чтобы сбалансировать затраты на выделение времени на другой процессор или ядро ​​с кратковременным голоданием. На архитектурах, где это имеет значение, результат имеет тенденцию напоминать автоматическое родство. ОС была построена вокруг того, чтобы все задания выполнялись как можно быстрее, и вы можете стрелять себе в ногу, привязывая потоки к ядрам и ограничивая его способность принимать такие решения.
Blrfl
-1

У меня когда-то была огромная среда SGI IRIX. Просто ради этого я написал небольшую многопоточную Java-программу (которая просто ничего не делала, но потребляла циклы ЦП) и создал в ней 12 потоков. Работа охватила 12 процессоров в архитектуре NUMA. Может быть, я посмотрю программу и запустим ее на Dell R910s и проверим ..

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