Как планируются легкие потоки ядром linux в многоядерной многоядерной SMP-системе?
Я использую параллельный алгоритм, используя легкие потоки, и мне интересно, как они назначаются разным ядрам, когда система предоставляет несколько ядер и несколько чипов. Связаны ли потоки с одним чипом, пока все ядра на чипе не будут исчерпаны? Распределены ли потоки между ядрами на разных чипах, чтобы лучше распределять работу между чипами?
2 ответа
Вы не говорите, в какой ОС вы работаете, но в Linux потоки назначаются ядру в зависимости от нагрузки на это ядро. Поток, готовый к запуску, будет назначен ядру с самой низкой нагрузкой, если вы не укажете иное, установив привязку потока. Вы можете сделать это с sched_setaffinity()
, Смотрите man-страницу для более подробной информации. В общем, как сказал meyes1979, это то, что решает планировщик, реализованный в используемой вами ОС.
В зависимости от версии Linux, которую вы используете, могут быть полезны две статьи: в этой статье описываются ядра ранних версий 2.6, начиная с версии 2.6.22, и в этой статье описываются ядра новее, чем 2.6.23.
Различные библиотеки потоков выполняют операции потоков по-разному. В наши дни "стандартом" в Linux является NPTL, который планирует потоки на том же уровне, что и процессы. Это вполне нормально, поскольку процесс создания в Linux быстрый, и он всегда должен оставаться быстрым.
Ядро Linux пытается обеспечить очень сильное сходство ЦП с выполняющимися процессами и потоками, чтобы увеличить соотношение попаданий в кэш и промахов в кэше - если задача всегда выполняется на одном и том же ядре, она, скорее всего, будет иметь предварительно заполненные строки кэша.
Обычно это хорошо, но я заметил, что ядро не всегда может переносить задачи с занятых ядер на незанятые. Это поведение может меняться от версии к версии, но я обнаружил, что несколько задач, связанных с процессором, выполняются на одном ядре, а три других ядра простаивают. (Я нашел это, заметив, что одно ядро было на шесть или семь градусов Цельсия теплее, чем три других.)
В общем, правильная вещь должна просто случиться; но когда ядро не переносит задачи автоматически на другие процессоры, вы можете использовать taskset(1)
команда, чтобы ограничить процессоры, разрешенные для программ, или вы можете изменить вашу программу, чтобы использовать pthread_setaffinity_np(3)
функция для запроса отдельных потоков для миграции. (Возможно, это лучше всего подходит для внутренних приложений - один из ваших пользователей может не захотеть, чтобы ваша программа использовала все доступные ядра. Если вы решите включить вызовы этой функции в вашу программу, убедитесь, что она настраивается через файлы конфигурации для обеспечить функциональность, аналогичную taskset(1)
программа).