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

11274
developer747

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

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

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

21
Предполагая, что среда выполнения C # использует эквивалентные собственные системные вызовы для порождения другого потока (и, таким образом, действительно параллельна; это не относится ко всему, как печально известная CPython [Global Interpreter Lock] (http://en.wikipedia.org/wiki/) Global_Interpreter_Lock)), это будет зависеть исключительно от [планировщика процессов / задач] операционной системы (https://en.wikipedia.org/wiki/Scheduling_%28computing%29). Тем не менее, в целом, код является действительно поточно-ориентированным, если вы предполагаете, что `t1` и` t2` выполняются в разное время в произвольном порядке (например, возможно, что `t2` запускается * до *` t1` в некоторых моделях). Breakthrough 11 лет назад 1
Я не знал, что существуют процессоры Pentium i5. Может ты имел ввиду Core i5? Picky. Я знаю: D JosephGarrone 11 лет назад 2

2 ответа на вопрос

18
BlueRaja - Danny Pflughoeft

You cannot guarantee in .Net that two Threads run on two separate cores. In fact, you also cannot guarantee that one Thread will run on only one core(!).

This is because managed threads are not the same as OS threads - a single managed Thread may use multiple OS threads to support it. In C#, you only ever deal directly with managed Threads (at least, without resorting to p/invoke to call the WinAPI threading functions, which you should never do).

However, the .Net and Windows thread schedulers are very good at what they do - they wouldn't run two threads on a single core while a second core sits completely idle. So, in general, you don't need to worry about it.

На практике .Net `Thread`s * - это * потоки ОС. Но это не то, почему нет гарантии, что один поток всегда будет выполняться на одном и том же ядре. svick 11 лет назад 0
@svick: На практике ** на x86 ** это правда. Однако в стандарте прямо говорится, что вы не можете полагаться на это поведение, поэтому оно может измениться в будущем. На самом деле, это * не * верно для других версий .Net CLR, таких как XBox 360. BlueRaja - Danny Pflughoeft 11 лет назад 2
@BlueRaja - Вопрос конкретно о том, о какой версии CLR мы говорим. Вы можете гарантировать, что что-то будет существовать на двух отдельных ядрах, используя асинхронные потоки, потому что это будет означать, что они будут асинхронными друг от друга. Текущий пример кода технически является синхронизирующим вызовом. Конечно, операционная система решает, какие ядра будут использоваться. Ramhound 11 лет назад 0
@Ramhound * «Вы можете гарантировать, что что-то будет существовать на двух отдельных ядрах, используя асинхронные потоки» * - это неверно. Ключевое слово `async` * (это, как я полагаю, вы говорите, поскольку« асинхронные потоки »является избыточным) * является просто синтаксическим сахаром для использования потока` BackgroundWorker`, который похож на любой другой поток .Net - вы можете ' не гарантирует, будет ли он работать на отдельном ядре или нет. BlueRaja - Danny Pflughoeft 11 лет назад 0
@BlueRaja - Если бы два асинхронных потока были запущены, они оба запустились бы одновременно, если бы было 2 ядра ЦП. Если бы был только один, то операционная система планировала бы, когда каждый поток получит приоритет и запустится, и произойдет ваша типичная однопотоковая ситуация перебивания. Так меня учили, как процессор обрабатывает многопоточность. Ramhound 11 лет назад 0
@Ramhound: Ваше понимание близко, но ошибочно. Даже если у компьютера два ядра, ОС не обязательно «запланирует» оба потока на отдельные ядра * (например, в настоящее время она может использовать одно из ядер для чего-то более высокого приоритета) *. В этом случае оба потока будут запланированы на одно и то же ядро, и произойдет обычное переключение контекста * (что должно произойти в любом случае; на нормальном ПК одновременно работают десятки процессов!) *. Кроме того, это не называется «избиение» - это нечто [совершенно другое] (http://en.wikipedia.org/wiki/Thrashing_%28computer_science%29). BlueRaja - Danny Pflughoeft 11 лет назад 0
@BlueRaja - Вы действительно правы. Трэшинг - это нечто иное, конкретный термин, который я ищу, в настоящее время ускользает от меня. Я полагаю, что двум асинхронным потокам может быть дано одно и то же ядро, и им будет сложно найти слова, чтобы точно описать, о чем я думаю, поэтому я просто отброшу их. Ramhound 11 лет назад 0
15
Frank Thomas

No, the OS and CPU will decide what to run and when. in the simple example you have shown, to the exclusion of other tasks, yes those would most likely run in parallel on separate cores, but there is rarely a guarantee that that will be the case.

You can use the thread affinity to attempt to take some control over the allocation of a core to a given thread.

Also consider scheduling priorities to stack the deck in terms of which threads should be entirely parallel, and which can wait.

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

Похожие вопросы