Многоядерное использование, потоки, пулы потоков - PullRequest
9 голосов
/ 28 декабря 2008

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

В частности, мне интересно, как операционная система и / или инфраструктура (это .NET) работает с интенсивно используемыми ядрами.

Вот мои вопросы относительно тем:

  • Когда создается новый поток, каков алгоритм назначения потока конкретному ядру?
    1. Алгоритм циклического типа
    2. Random
    3. наименее используемое ядро ​​
  • Если бы не наименее используемое в настоящее время ядро, был бы этот тип кода, который определял это карликовое типичное использование потока, и, таким образом, только ухудшал бы положение?
  • Перемещаются ли потоки из одного ядра в другое в течение срока их службы? Если да, то это для обработки ядер, которые по какой-то причине «чрезмерно используются», и, таким образом, операционная система пытается перетасовать потоки на менее используемые ядра, чтобы помочь системе? Если нет, то почему бы и нет?

Мой последний вопрос, который по сути является повторным использованием вышеизложенного, касается класса .NET ThreadPool, который обрабатывает такие вещи, как .BeginInvoke и тому подобное. Этот класс делает что-нибудь из этого? Если нет, то почему бы и нет?

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

Ответы [ 2 ]

18 голосов
/ 28 декабря 2008

Когда создается новая тема, что алгоритм назначения потока к конкретному ядру?

Это полностью зависит от ОС. И ответом обычно является сильно модифицированная круговая схема. Каждые x миллисекунд ядро ​​прерывается, и на него помещается новый поток (поэтому нет «наименее используемого ядра». Пока есть готовые к работе потоки, каждому ядру будет чем заняться).

В Windows я считаю, что поток / процесс с самым высоким приоритетом всегда выбран для выполнения. (Таким образом, если у вас есть один процесс с высоким приоритетом в одноядерной системе, этот процесс потенциально может выполняться 100% времени, что приводит к истощению всех остальных процессов. Конечно, это применимо, только если этот процесс никогда не блокируется, что маловероятно в реальный мир.

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

В Linux процессы с более низким приоритетом также регулярно планируются, но не так часто.

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

Переносятся ли потоки из одного ядра в другой при жизни?

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

Мой последний вопрос, который в основном повторное использование выше, о Класс .NET ThreadPool, который обрабатывает такие вещи, как .BeginInvoke и такие. Этот класс делает что-нибудь из этого? Если нет, то почему бы и нет? Какие вещи? Планирование потоков и выбор ядер для запуска? Нет, пул потоков - это просто механизм повторного использования потоков для нескольких задач, вместо того, чтобы создавать новый поток для каждой отдельной задачи, а затем закрывать его.

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

Вот для чего приоритет потока / процесса. Если у вас есть поток, который должен получать много процессорного времени, даже если запущены другие потоки с интенсивным использованием процессора, увеличьте приоритет потока. Но обращаться с осторожностью. Обычно не так много запущенных потоков, интенсивно использующих процессор, а это значит, что даже при обычном приоритете вы получите 99,9% процессорного времени. Как я уже говорил, Windows очень агрессивно планирует потоки с более высоким приоритетом, поэтому повышайте приоритет только в том случае, если вы действительно имеете это в виду.

6 голосов
/ 28 декабря 2008

В дополнение к превосходному и исчерпывающему ответу jalf, имейте в виду, что "Parallel Extensions" (который должен быть свернут в .NET 4.0) имеет lot кода, предназначенного для распределения работы (из очередей) на ядра равномерно, включая кражу работы, и потенциально самородки, такие как забота о том, какое ядро ​​«ближе всего» к памяти, в которой находится произведение.

Таким образом, в .NET 4.0, используя такие вещи, как Parallel.For и т. Д., Вы должны получить многое из этого бесплатно. И вообще, ОС достаточно умна, чтобы она просто работала с точки зрения постороннего. jalf дал много подробностей о том, что происходит под капотом, но в большинстве случаев вам не нужен этот уровень детализации, если только вы не решаете некоторые проблемы с производительностью с помощью многопоточного кода.

...