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

24

У меня процессор Pentium Core i5, который имеет 4 ядра. Если я делаю это в консольной программе C #

var t1 = new Thread(Thread1);
var t2 = new Thread(Thread2);
t1.Start();
t2.Start();

потоки t1 и t2 гарантированно работают на отдельных ядрах?

developer747
источник
1
Предполагая, что среда выполнения C # использует эквивалентные собственные системные вызовы для порождения другого потока (и, таким образом, действительно параллельна; это не относится ко всему, как печально известная глобальная блокировка интерпретатора CPython ), это будет зависеть исключительно от планировщика процессов / задач операционной системы . Вообще , хотя, код действительно поточен если предположить , что t1и t2выполняются в разное время в произвольном порядке (например , это возможно t2начинается до t1 того, в некоторых моделях).
Прорыв
2
Я не знал, что есть процессоры Pentium i5. Может ты имел ввиду Core i5? Picky. Я знаю: D
JosephGarrone

Ответы:

18

В .Net нельзя гарантировать, что два Threadработают на двух разных ядрах. Фактически, вы также не можете гарантировать, что он Threadбудет работать только на одном ядре (!) .

Это связано с тем, что управляемые потоки не совпадают с потоками ОС - один управляемый поток может использовать несколько потоков ОС для его поддержки. В C # вы когда-либо имеете дело только с управляемыми Threads (по крайней мере, не прибегая к p / invoke для вызова потоковых функций WinAPI, чего вы никогда не должны делать) .

Тем не менее, планировщики потоков .Net и Windows очень хороши в том, что они делают - они не запускают два потока на одном ядре, пока второе ядро ​​находится в режиме ожидания. Так что, в общем, вам не нужно беспокоиться об этом.

BlueRaja - Дэнни Пфлугхофт
источник
На практике .Net Threads являются OS темы. Но это не то, почему нет гарантии, что один поток всегда будет выполняться на одном и том же ядре.
svick
2
@svick: На практике на x86 это правда. Однако в стандарте прямо говорится, что вы не можете полагаться на это поведение, поэтому оно может измениться в будущем. На самом деле, это не так в других версиях .Net CLR, таких как XBox 360.
BlueRaja - Дэнни Пфлугхофт
@BlueRaja - Вопрос конкретно о том, о какой версии CLR мы говорим. Вы можете гарантировать, что что-то будет существовать на двух отдельных ядрах, используя асинхронные потоки, потому что это будет означать, что они будут асинхронными друг от друга. Текущий пример кода технически является синхронизирующим вызовом. Конечно, операционная система решает, какие ядра будут использоваться.
Ramhound
@Ramhound «Вы можете гарантировать, что что-то будет существовать на двух отдельных ядрах, используя асинхронные потоки» - это неверно. asyncКлючевое слово (что я предполагаю , что вы говорите, как «асинхронными потоками» является излишним) просто синтаксический сахар для использования BackgroundWorkerнити, которая , как и любой другой .Net теме - вы можете не гарантия того , что будет работать на отдельное ядро ​​или нет.
BlueRaja - Дэнни Пфлугхофт
@BlueRaja - Если бы два асинхронных потока были запущены, они оба работали бы одновременно, если было 2 ядра ЦП. Если бы был только один, то операционная система планировала бы, когда каждый поток получит приоритет и запустится, и произойдет ваша типичная однопотоковая ситуация перебивания. Так меня учили, как процессор обрабатывает многопоточность.
Ramhound
15

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

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

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

Фрэнк Томас
источник
1
Я также хочу добавить, что с технологиями виртуализации существует еще один слой между вашей программой и оборудованием. То, что ОС представляет приложению, может быть физически неточным.
Келтари
1
Это функции WinAPI для потоков ОС, а не для управляемых потоков. Их никогда не следует вызывать из C #, поскольку они могут серьезно помешать планировщику потоков .Net.
BlueRaja - Дэнни Пфлюгофт