В моей программе есть несколько потоков, которые запускаются вместе с процессом и остаются до завершения программы. Они будут сталкиваться с различными нагрузками в течение жизненного цикла приложения, и временами они все будут работать на 100%.
По умолчанию планировщик потоков Linux будет изменять сродство на многоядерной системе для этих потоков довольно легкомысленно, на мой взгляд. Когда я смотрю на графики подпрыгивания в моем графическом мониторе процессов (том, что в gnome), я не могу не думать, что это представляет собой своего рода накладные расходы.
РЕДАКТИРОВАТЬ:Для ясности: даже при очень стабильных нагрузках потоки распределяются по разным ядрам, и хотя на представленном изображении это не видно, порой совершенно ясно, что ядро, выбранное для каждого потока, часто «меняется местами».
Не повлияет ли это постоянное изменение сродства отрицательно на производительность?
В таком случае, почему это реализовано именно так? Какие преимущества дает изменение сродства?
Мои предположения таковы:
- Выравнивание износа — не возлагайте всю работу на одно ядро
- Непреднамеренно — некоторые интеллектуальные алгоритмы пытаются оптимизировать использование в зависимости от нагрузки, и так получается, что накладные расходы не настолько значительны, чтобы оправдать сохранение соответствия вместо его изменения.
решение1
Если вы собираетесь запускать все потоки на одном ядре, купите более дешевое оборудование с одним ядром.
Планировщик пытается максимально использовать все ядра. Это означает, что потоки направляются на любое ядро, у которого есть свободное время. Перемещение потока с одного ядра на другое имеет небольшие затраты, поэтому планировщик пытается этого избежать. Но вы обычно не заметите этого, потому что выгода от того, чтобы ядро не простаивало, намного больше, чем затраты на миграцию потока. Это особенно верно, если потоки используют больше памяти, чем у вас есть в локальном кэше ядра: если память, используемая потоком, не находится в локальном кэше ядра, то очень мало что может быть потеряно при миграции на другое ядро.
Сомнения в эффективности промышленного планировщика, например, Linux, обычно приводят к снижению производительности.
Графики, которые вы показываете, показывают, что нагрузка на различные ядра не полная и слегка изменчива, предположительно потому, что ваша система в целом ограничена вводом-выводом для задач, которые она выполняет прямо сейчас, а не мощностью ЦП. Это ничего не говорит о том, как часто потоки перемещаются с одного ядра на другое.
решение2
Представленный здесь снимок также зависит от типа (версии) ядра. Старые ядра с версией 2.4 имели плохое сродство, что вызывало много пинг-понговых перемещений потоков, влияющих на производительность системы. Версии ядра от 2.5 имеют относительно лучшее сродство.
В многоядерной системе настройка привязки может повысить производительность, предотвращая возникновение случаев недействительности кэша при перемещении потока между ядрами.
В случае многоядерной системы на базе Linux поведение привязки планировщика (естественная привязка) можно переопределить в зависимости от типа приложения/требования, используя sched_setaffinity/taskset для процесса и pthread_setaffinity_np для потока.
kernelsharkпо-видимому, обеспечивает лучшее визуальное представление многоядерной системы и ее соответствия.
Также обратите внимание, чтоhtopобеспечить визуальную поддержку для установки соответствия (для переопределения планировщика).