Минимизируйте количество многоядерных переключателей контекста - PullRequest
3 голосов
/ 28 июля 2010

В последнее время я много экспериментировал с профилированием приложений (с помощью Visual Studio Performance Wizard).Работая с индикаторами параллелизма, я заметил тот факт, что когда приложение запускается с несколькими потоками (как фоновым, так и передним), частота переключения между ядрами довольно высока.

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

Каковы возможные способы сделать это в приложении .NET, помимо минимизации количества одновременно работающих потоков

Ответы [ 2 ]

2 голосов
/ 26 июня 2013

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

Любое переключение контекста влечет за собой прямые затраты ~ 1-4 микросекунды для сохранения / восстановления состояния потока, а также косвенные затраты на разогрев кеша. Косвенная стоимость зависит от многих факторов, таких как локальность данных и схемы доступа, и варьируется в широких пределах: от сотен наносекунд, практически ничего не добавляя к общей стоимости переключения контекста, до сотен микросекунд, увеличивая общую стоимость на два порядка.

Хотя вполне разумно ожидать, что разогрев кеша займет больше времени для многоядерного переключения контекста (если новое ядро ​​не разделяет кеши со старым), планирование потока на том же ядре все равно потребует Разогрев кеша, поскольку некоторые или все данные потока будут вытеснены из кеша другими потоками, выполняемыми на этом промежуточном ядре.

В любом случае общая стоимость переключения контекста все равно будет незаметна по сравнению с ~ 30-120 миллисекундами кванта выполнения потока (время между переключениями контекста).

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

В качестве примечания, вопреки совету Л.Бушкина, BeginThreadAffinity не поможет вам в привязке к процессору: он только привязывает поток .NET к конкретному потоку ОС, не к конкретному ядру.

Полезные ссылки:

[1] Использование параллелизма для масштабируемости
[2] Количественная оценка стоимости переключения контекста
[3] Сколько времени занимает переключение контекста?

1 голос
/ 28 июля 2010

Вы можете привязать некоторые из этих потоков к одному ядру.Но вы должны быть предельно осторожными при этом - поскольку это может фактически снизить производительность, не позволяя CLR / OS планировать потоки на доступные ядра.

Для этого вы можете использовать BeginThreadAffinity метод, чтобы заставить поток оставаться закрепленным за идентификатором конкретного процессора или ядра.

...