Действительно ли потоки из нескольких процессов выполняются одновременно?

В операционной системе Windows с 2 физическими процессорами x86/amd64 (P0 + P1), запущенными 2 процессами (A + B), каждый с двумя потоками (T0 + T1), возможно (или даже часто) увидеть следующее:

P0:A:T0 работает одновременно с P1:B:T0

затем, после 1 (или 2?) переключения контекста (ов?)

P0:B:T1 работает одновременно с P1:A:T1

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

EDIT: Чтобы прояснить глупый пример, представьте, что поток A:T0 процесса A имеет сходство с процессором P0 (и A:T1 с P1), в то время как поток B:T0 процесса B имеет сходство с процессором P1 ( и B:T1 до P0). Вероятно, не имеет значения, являются ли эти процессоры ядрами или сокетами.

Существует ли первоклассная концепция переключения контекста процесса? Perfmon показывает переключение контекста в объекте Thread, но ничего в объекте Process.


person Jono    schedule 04.06.2010    source источник
comment
Обратите внимание, что типичной ОС все равно, насколько физически удалены два ядра: на одном и том же кристалле, на двух кристаллах в одном сокете или даже в разных сокетах. По крайней мере, до тех пор, пока два ядра используют одну неинформативную память. Архитектуры NUMA — еще один зверь.   -  person MSalters    schedule 04.06.2010
comment
Интересно, я не рассматривал гиперпоточность, но предположим, что если ОС не может определить разницу, значит ли это, что на одном сокете, одноядерном процессоре с гиперпотоком есть шанс, что два потока могут принадлежать разным процессам?   -  person Jono    schedule 04.06.2010


Ответы (2)


Да, это возможно, и это случается довольно часто.
ОС пытается не переключать один поток между процессорами (вы можете усложнить задачу, установив для потоков предпочитаемый процессор, или вы даже можете привязать его к одному процессору через affinity).
Процесс Windows сам по себе не является исполняющей единицей — с этой точки зрения, это просто контекст для его потоков.

ИЗМЕНИТЬ (дополнительные пояснения)

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

Этот «скачок» может показаться дорогим, учитывая, что по крайней мере кэши L1 (а иногда и L2) являются поядерными (не считая разных процессоров слотов/пакетов), но это все же дешевле, чем задержки, вызванные ожиданием «нужного» процессора и невозможностью выполнить тщательно продуманную балансировку нагрузки (что делает возможной "прыгающая" схема).
Это может неприменимо к архитектуре NUMA, но есть гораздо больше соображений (например, адаптация всей памяти- выделения должны быть привязаны к потокам и процессора и максимально избегать совместного использования состояния/памяти).

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

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

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

Любой поток по умолчанию будет переключаться между доступными логическими процессорами (особенно если он уступает, обращается к ядру и т. д.), < em>может перейти, даже если для него установлен предпочтительный процессор, но только если это необходимо, но НЕ будет< /strong> перейти к процессору за пределами его маски сходства (что может привести к значительным задержкам).

Я не уверен, видит ли планировщик какую-либо разницу между физическими и многопоточными процессорами, но даже если и не видит (что я предполагаю), последствия в большинстве случаев не вызывают беспокойства, т.е. не должно может быть значительная разница между несколькими потоками, совместно использующими физические или логические процессоры, если количество потоков одинаково. Несмотря на это, есть некоторые сообщения о перегрузке кеша в этом сценарии, в основном в высокопроизводительных многопоточных приложениях, таких как SQL Server или виртуальные машины .NET и Java, которые могут может не выиграть от отключения HyperThreading.

person Viktor Svub    schedule 04.06.2010
comment
Я вполне уверен, что это немного сложнее, чем это. Все потоки одного процесса совместно используют одно и то же виртуальное адресное пространство, которое (за исключением разделяемой памяти) не пересекается с адресным пространством другого процесса. Это также означает, что для ОС полезно хранить потоки одного процесса на одном ядре — меньше контекста для перезагрузки. - person MSalters; 04.06.2010
comment
@MSalters: я согласен с тем, что должны быть некоторые дополнительные затраты на переключение контекста, когда потоки из разных процессов, но не согласен, что для ОС автоматически полезно пытаться сохранить потоки на одном ядре, особенно с учетом количества доступных процессоров увеличивается. Было бы интересно количественно оценить дополнительные затраты на переход от одного виртуального адресного пространства к другому сверх затрат на переключение потоков. - person Jono; 04.06.2010
comment
Спасибо за редактирование, Виктор. Очень информативно. Я сомневаюсь, что есть очень много вопросов о параллелизме, которые на самом деле не могут быть оговорены, это немного сложнее... но хорошее приближение к истине - как это - укажет мне правильное направление. - person Jono; 05.06.2010

Я в целом согласен с предыдущим ответом, однако все сложнее.

Хотя процессы не являются исполняющими единицами, потоки, принадлежащие одному и тому же процессу, должны обрабатываться по-разному. На это есть две причины:

  1. Одно и то же адресное пространство. Значит - при переключении контекста между такими потоками не нужно настраивать регистры трансляции адресов.
  2. Потоки одного и того же процесса с гораздо большей вероятностью будут обращаться к одной и той же памяти.

(2) оказывает большое влияние на состояние кеша. Если потоки читают одно и то же место в памяти - они повторно используют кеш L2, следовательно, все ускоряется. Однако есть и недостаток: как только поток меняет место в памяти, этот адрес становится недействительным как в кеше L2, так и в кеше L2 обоих процессоров, так что другой процессор также аннулирует свой кеш.

Таким образом, есть плюсы и минусы одновременного запуска потоков одного и того же процесса (на разных процессорах). Кстати, у этой ситуации есть название: «Групповое планирование».

person valdo    schedule 04.06.2010