Подтвердить что ты не робот

Стоимость переключения контекста между потоками одного процесса, на Linux

Есть ли хорошие эмпирические данные о стоимости переключения контекста между потоками одного и того же процесса в Linux (в основном интересны x86 и x86_64)? Я говорю о количестве циклов или наносекунд между последней инструкцией, которую один поток выполняет в пользовательском пространстве, прежде чем получить добровольно или непроизвольно спать, а первая команда - другой поток того же процесса, выполняющийся после пробуждения на одном процессоре/ядре.

Я написал программу быстрого тестирования, которая постоянно выполняет rdtsc в 2 потоках, назначенных одному и тому же процессору/ядру, сохраняет результат в переменной volatile и сравнивается со своей дочерней нитью, соответствующей переменной volatile. В первый раз, когда он обнаруживает изменение значения сестринского потока, он печатает разницу, а затем возвращается к циклу. Я получаю минимальный/средний подсчет около 8900/9600 циклов таким образом на процессоре Atom D510. Эта процедура кажется разумной, и цифры кажутся правдоподобными?

Моя цель состоит в том, чтобы оценить, может ли в современных системах модель сервера нитей за соединение быть конкурентоспособной или даже превосходить мультиплексирование выборочного типа. Это кажется правдоподобным в теории, поскольку переход от выполнения IO на fd X к fd Y предполагает просто переходить в спящий режим в одном потоке и просыпаться в другом, а не в нескольких системных вызовах, но он зависит от накладных расходов при переключении контекста.

4b9b3361

Ответ 1

(Отказ от ответственности: это не прямой ответ на вопрос, просто некоторые предложения, которые, я надеюсь, будут полезны).

Во-первых, цифры, которые вы получаете, безусловно, звучат так, как будто они находятся в пределах стадиона. Обратите внимание, однако, что латентность прерываний/ловушек может сильно различаться между различными моделями ЦП, реализующими ту же самую ISA. Это также другая история, если ваши потоки использовали операции с плавающей запятой или вектором, потому что, если у них нет ядра, можно избежать сохранения/восстановления состояния с плавающей точкой или вектора.

Вы можете получать более точные цифры с помощью инфраструктуры отслеживания ядра - perf sched, в частности, предназначен для измерения и анализа планировщика латентность.

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

Обратите внимание, что на хорошо написанном сервере мультиплексирования при большой нагрузке переход от fd X в fd Y часто будет включать один и тот же системный вызов (так как сервер выполняет итерацию над списком активных файловых дескрипторов, возвращаемых из один epoll()). Один поток также должен иметь меньший размер кеша, чем несколько потоков, просто имея только один стек. Я подозреваю, что единственный способ урегулировать этот вопрос (для некоторого определения "уладить" ) может означать повторную перестрелку...