Как изменить длину временных интервалов, используемых планировщиком ЦП Linux?

Можно ли увеличить продолжительность временных интервалов, для которых планировщик ЦП Linux позволяет запускать процесс? Как я мог это сделать?

Жизненный опыт

В этом вопросе задается вопрос, как уменьшить частоту, с которой kernel ​​будет принудительно переключаться между разными процессами, работающими на одном и том же процессоре. Эта функция ядра описана как «упреждающая многозадачность». Эта функция, как правило, хороша, потому что она останавливает отдельный процесс, загружающий процессор и делающий систему полностью не отвечающей на запросы. Однако переключение между процессами имеет свою стоимость , поэтому существует компромисс.

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

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

мотивация

Я публикую это, основываясь на моей первоначальной реакции на вопрос Как изменить частоту переключения контекста в Linux?

Я лично не хочу менять временную шкалу. Однако я смутно помню, как это было с CONFIG_HZ сборки CONFIG_HZ . Поэтому я хочу знать, какова текущая ситуация. CONFIG_HZ планировщика ЦП по-прежнему основан на CONFIG_HZ ?

Кроме того, на практике настройка времени сборки очень ограничивает. Для дистрибутивов Linux гораздо практичнее, если они могут иметь одно kernel ​​на архитектуру ЦП и позволяют настраивать его во время выполнения или, по крайней мере, во время загрузки. Если настройка временного интервала все еще актуальна, существует ли новый метод, который не блокирует его во время сборки?

Для большинства серверов RHEL7 RedHat предлагает увеличить sched_min_granularity_ns до 10 мс и sched_wakeup_granularity_ns до 15 мс. ( Источник . Технически эта ссылка говорит 10 мкс, что будет в 1000 раз меньше. Это ошибка).

Мы можем попытаться понять это предложение более подробно.

Увеличение sched_min_granularity_ns

В современных ядрах Linux временные интервалы ЦП распределяются между задачами с помощью CFS, полностью честного планировщика. CFS можно настроить с помощью нескольких настроек sysctl .

  • kernel.sched_min_granularity_ns
  • kernel.sched_latency_ns
  • kernel.sched_wakeup_granularity_ns

Вы можете установить sysctl временно до следующей перезагрузки или навсегда в файле конфигурации, который применяется при каждой загрузке. Чтобы узнать, как применить этот тип настроек, посмотрите «sysctl» или прочитайте краткое введение здесь .

sched_min_granularity_ns является наиболее заметным параметром. В оригинальном sched-design-CFS.txt это было описано как единственный «настраиваемый» параметр, «чтобы настроить планировщик с« настольных »(с малыми задержками) на« серверные »(с хорошими пакетными) рабочими нагрузками».

Другими словами, мы можем изменить этот параметр, чтобы уменьшить накладные расходы при переключении контекста и, следовательно, повысить пропускную способность за счет скорости отклика («задержки»).

Я считаю эту настройку CFS имитирующей предыдущую настройку времени сборки, CONFIG_HZ . В первой версии кода CFS значение по умолчанию составляло 1 мс, что эквивалентно 1000 Гц для использования «на рабочем столе». Другие поддерживаемые значения CONFIG_HZ были 250 Гц (по умолчанию) и 100 Гц для конца «сервер». 100 Гц также было полезно при работе Linux на очень медленных процессорах, это было одной из причин, приведенных при первом добавлении CONFIG_HZ в качестве параметра сборки на X86 .

Разумно попытаться изменить это значение до 10 мс (т.е. 100 Гц) и измерить результаты. Помните, что sysctl измеряются в нс . 1 мс = 1 000 000 нс.

Мы можем видеть, что эта старая школа настройки для «сервера» все еще была очень актуальна в 2011 году для пропускной способности в некоторых тестах высокой нагрузки: https://events.static.linuxfound.org/slides/2011/linuxcon/lcna2011_rajan.pdf

И, возможно, пара других настроек

Значения по умолчанию трех указанных выше настроек выглядят относительно близко друг к другу. Это заставляет меня хотеть держать вещи простыми и умножать их все на один и тот же фактор :-). Но я попытался разобраться в этом, и кажется, что некоторые более специфичные настройки также могут иметь значение, поскольку вы настраиваете пропускную способность.

sched_wakeup_granularity_ns относится к “упреждению пробуждения”. Т.е. он контролирует, когда задача, вызванная событием, может немедленно опередить текущий запущенный процесс. Слайды 2011 года показали различия в производительности и для этого параметра.

См. Также «Отключить WAKEUP_PREEMPT» в этом справочнике IBM за 2010 год , в котором говорится, что «для некоторых рабочих нагрузок эта функция по умолчанию« может стоить несколько процентов загрузки ЦП ».

В SUSE Linux есть документ, который предлагает установить значение больше половины sched_latency_ns чтобы эффективно отключить упреждение пробуждения, а затем «задачи с коротким рабочим циклом не смогут эффективно конкурировать с нагрузками на ЦП».

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

https://www.suse.com/documentation/opensuse121/book_tuning/data/sec_tuning_taskscheduler_cfs.html

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

Предложение, если ваша рабочая нагрузка имеет большое количество streamов / процессов

Я также натолкнулся на предложение 2013 года для нескольких других параметров, которые могут получить значительную пропускную способность, если ваша рабочая нагрузка имеет большое количество streamов. (Или, может быть, точнее, он восстанавливает пропускную способность, которую они получили на ядрах до CFS).

Игнорировать CONFIG_HZ

Я думаю, вам не нужно беспокоиться о том, что установлено в CONFIG_HZ . Насколько я понимаю, это не относится к текущим ядрам, если у вас есть разумное оборудование таймера. См. Также commit 8f4d37ec073c, “sched: тик с высоким разрешением” , найденный с помощью этого комментария в ветке об изменении: https://lwn.net/Articles/549754/ .

(Если вы посмотрите на коммит, я бы не стал беспокоиться, что SCHED_HRTICK зависит от X86 . Это требование, по-видимому, было отброшено в некоторых более поздних коммитах).

Похоже, вам нужен пакетный планировщик: используйте schedtool для запуска процессов под разными планировщиками. например, schedtool -B «Command to be run in batch mode»

(это должен быть комментарий, но это немного долго)

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

Только если kernel ​​выполняет приоритетное выполнение задач и возвращает их в очередь выполнения.

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