CNXSoft: Это гостевой пост от Дэниела Томпсона, главного инженера по программному обеспечению в RISCstar Solutions , об управлении энергопотреблением CPU в Linux для встроенных систем, с углубленным рассмотрением cpuidle.
Двадцать лет назад ядру операционной системы было легко перейти в режим простоя: когда не было задач для выполнения, планировался «цикл простоя». Ранние циклы простоя представляли собой по сути пустые бесконечные циклы, которые ничего не делали в ожидании следующего прерывания. Это позволяло экономить энергию просто за счет избегания выполнения инструкций, требовавших энергоемких компонентов, таких как кэш или FPU!
Со временем развитие технологий позволило внедрить множество дополнительных аппаратных механизмов для снижения энергопотребления. При наличии этих новых возможностей сегодня, цикл простоя отвечает за выбор и применение «наилучшего» способа перехода в режим простоя.
Напоминанием, вход в состояние простоя и выход из него имеет свою стоимость, которую можно измерить как во времени, так и в энергии. Как правило, самый «мелкий» режим простоя требует для входа/выхода «почти нулевых» затрат, в то время как более «глубокие» режимы имеют все более высокую стоимость входа и выхода. Если система входит в глубокий режим простоя и пробуждается вскоре после засыпания, то энергия будет потрачена впустую, потому что затраты энергии на вход в глубокий режим простоя превышают сэкономленную энергию за время пребывания в этом состоянии.
cpuidle — это подсистема ядра, управляющая переходами между состояниями простоя. Как и в cpufreq, механизм отделен от политики с использованием драйверов и регуляторов.
- cpuidle драйверы предоставляют механизм для входа в состояние простоя и выхода из него. Они перечисляют доступные состояния простоя для регулятора. При этом они описывают регулятору энергосберегающие свойства каждого состояния. Наконец, драйверы могут переводить CPU в состояние простоя по запросу регулятора.
Драйверы могут быть полностью настроены с учетом уникальных свойств каждого System-on-Chip (SoC). Однако состояния простоя CPU часто хорошо поддерживаются низкоуровневым микропрограммным обеспечением платформы и становятся доступными ядру через стандартные интерфейсы, такие как PSCI (Power State Coordination Interface) на Arm и SBI (Supervisor Binary Interface) на RISC-V. Таким образом, хотя существует возможность создания драйверов для каждого SoC, на практике это становится редкостью. Большинство современных архитектур, включая Arm и RISC-V, определяют стандартизированные интерфейсы, позволяющие использовать единый драйвер для Arm и единый для RISC-V в широком спектре семейств SoC.
- cpuidle регуляторы предоставляют политику и отвечают за выбор «наилучшего» состояния простоя из доступных.
Регуляторы используют информацию от драйверов вместе со сбором данных об исторических или известных будущих событиях (например, таймерных пробуждениях), чтобы сделать «обоснованное предположение» о том, когда CPU потребуется выйти из состояния простоя из-за прерывания. Основываясь на расчетном времени пробуждения, он может выбрать состояние простоя, которое, вероятно, сэкономит наибольшее количество энергии.
Как регуляторы cpuidle принимают решения?
cpuidle регуляторы получают данные о физических характеристиках системы от драйвера cpuidle. Они представлены в виде списка состояний простоя, где каждое состояние аннотировано целевым временем пребывания (target residency). Целевое время пребывания — это минимальное время, которое CPU должен провести в состоянии простоя, чтобы сэкономить энергию по сравнению с более «мелкими» состояниями. Другими словами, хотя целевое время пребывания измеряется во времени, оно фактически предоставляет данные, позволяющие регулятору сравнивать энергетическую стоимость входа и выхода из различных состояний простоя. Есть три возможности, когда система покидает состояние простоя:
- Если система пробуждается до достижения целевого времени пребывания, то система потратила энергию впустую, выбрав слишком «глубокое» состояние простоя.
- Если система остается в состоянии простоя дольше, чем целевое время пребывания более «глубокого» состояния простоя (если такое есть), то система потратила энергию впустую, потому что более «глубокое» состояние сэкономило бы больше энергии.
- Если система была пробуждена после достижения целевого времени пребывания для выбранного состояния, но до достижения целевого времени более «глубокого» состояния, то выбор был оптимальным.
Все cpuidle регуляторы отслеживают исторические данные о времени входа/выхода в режим простоя; более того, они делают их видимыми для каждого CPU в /sys/devices/system/cpu/cpu/cpuidle, так что можно проверить их самостоятельно!
Регуляторы предполагают, что продолжительность недавних периодов простоя может использоваться для предсказания будущего. Фактически, регулятор ladder (используемый в системах с регулярным тиком планировщика) и регулятор haltpoll (специализированный регулятор для виртуальных машин) работают исключительно на основе исторических данных.
Другие регуляторы, такие как menu и teo (ориентированный на таймерные события), получают проблеск в будущее, хотя это видение довольно ограничено. В целом, драйверы не сообщают, когда они ожидают срабатывания своих прерываний, но есть одно прерывание, которое можно предсказать «идеально»: всегда известно, когда должно произойти следующее таймерное прерывание. Таким образом, верхняя граница любого периода простоя — это время до следующего таймерного прерывания. Для многих сценариев использования таймерные прерывания происходят значительно чаще любых других. Это означает, что если отслеживание истории входа/выхода указывает на то, что в основном доминируют таймерные прерывания, то это отличный предиктор времени простоя.
Последний фактор, играющий роль в решениях регулятора, — это энергетическая стоимость самого принятия решения! Любые вычисления имеют энергетическую стоимость. Неважно, если регулятор примет наилучшее решение, но потратит на его принятие слишком много энергии! Это особенно актуально, когда система испытывает короткие периоды простоя. В этом случае крайне желательно быстро принять решение о входе в самое «мелкое» состояние простоя!
Регуляторы menu и teo оба используют таймер для информирования решений, но применяют разные стратегии:
- Регулятор menu стремится сгенерировать предсказанное время сна, взяв время следующего пробуждения и применив корректирующий коэффициент, полученный из недавней истории. После составления прогноза он может выбрать наилучшее состояние простоя.
- Регулятор teo квантует историческую информацию в интервалы (бины) на основе целевого времени пребывания для каждого состояния простоя. Квантованная информация не позволяет предсказать время простоя, но поскольку каждый интервал соответствует конкретному состоянию простоя, регулятор все равно может предсказать, какое состояние будет лучшим! Затем он использует время следующего пробуждения для улучшения выбора, выбирая более «мелкий» режим, если таймер сработает в ближайшее время.
Дополнительные подробности о регуляторах menu и teo приведены в документации ядра Linux .
Настройка режима простоя для снижения энергопотребления
Все регуляторы cpuidle имеют кое-что общее с регулятором schedutil : сами регуляторы не предлагают каких-либо настраиваемых значений для изменения своих эвристик. Как было показано ранее, это не означает, что нам нечего настраивать, просто для экономии энергии (или повышения производительности) необходимо выйти за пределы самого регулятора. Далее рассмотрены некоторые из этих возможностей.
Переход на безтактовый режим
В течение многих лет Linux управлял течением времени, устанавливая таймер, срабатывающий 100 раз в секунду, и используя этот «планировщик тактов» для переключения процессов и обработки истечения таймеров в драйверах. Этот такт настраиваемый, и такт планировщика можно установить на 100, 250 или 1000 Гц. Изменение CONFIG_HZ может существенно повлиять на поведение системы и является интересным параметром настройки ядра при поиске баланса между энергопотреблением и отзывчивостью (хотя значение, приводящее к наименьшему потреблению энергии, зависит от рабочей нагрузки).
Когда CONFIG_HZ установлено на минимальное значение и система пробуждается 100 раз в секунду, система никогда не может находиться в состоянии простоя более 10 мс. Частые пробуждения могут снизить эффективность глубоких состояний покоя, и их следует избегать в системах, стремящихся экономить энергию таким образом.
Ядра в безтактовом режиме либо отключают такт планировщика, когда система переходит в состояние простоя (CONFIG_NO_HZ_IDLE=y), либо когда на CPU выполняется только одна задача
(CONFIG_NO_HZ_FULL=y). Установка любого из этих параметров позволяет увеличить время пребывания в состояниях простоя. Точная разница между этими вариантами тонкая и не входит в тему данного материала. См. NO_HZ: Уменьшение тактов планировщика , если интересно узнать больше!
Наконец, следует отметить, что переход в безтактовый режим бессмысленен, если есть драйвер, который пробуждается 100 раз в секунду для опроса, например, SPI-периферии. Если осуществляется переход на безтактовый режим, следует также убедиться, что код, выполняющийся в системе, не вводит ненужные периодические такты путем опроса состояния. Также важно отметить, что если опрос неизбежен, то все равно необходимо обеспечить отключение опроса драйвером при отсутствии клиентов.
Попробовать другой регулятор cpuidle
В безтактовой системе есть выбор из двух регуляторов: menu и teo (ориентированный на таймерные события).
Регулятор menu является регулятором по умолчанию и работает, предсказывая, как долго система будет находиться в состоянии простоя. Он отслеживает исторические интервалы пробуждения и время срабатывания следующего прерывания таймера, фильтруя их для определения «типичного» интервала пробуждения. Затем это предсказание используется для выбора из меню вариантов, предлагаемых драйвером cpuidle.
Регулятор teo использует те же источники данных, но отслеживает статистические данные, чтобы напрямую предсказать лучшее состояние покоя, не прогнозируя точно, как долго, как ожидается, система будет оставаться в простое. Когда система часто пробуждается, это позволяет избежать (относительно затратного) просмотра очереди таймеров, снижая энергетические затраты на принятие решений.
Регулятор можно проверить и изменить через sysfs: /sys/devices/system/cpu/cpuidle/current_governor.
Запросы качества обслуживания управления питанием (PM QoS)
Как упоминалось во вводных разделах, вход в состояние простоя и выход из него имеет стоимость, которую можно измерить как во времени, так и в энергии. Регулятор cpuidle обычно принимает решения на основе энергетических затрат, но бывают ситуации, когда необходимо учитывать и временные затраты. Например, если система находится в глубоком состоянии покоя, для возобновления работы CPU может потребоваться много времени. Что, если важное прерывание поступит во время глубокого состояния покоя и система не отреагирует достаточно быстро? Нежелательно, чтобы система в состоянии простоя приводила к срыву реальных временных ограничений, например, к нехватке данных в аудиобуфере.
Один из способов решения — отключить глубокое состояние покоя, но глобальное отключение приведет к ненужному расходу энергии, когда не выполняются чувствительные ко времени приложения.
Лучший способ решить эту проблему — обеспечить регистрацию всеми драйверами и пользовательским пространством своей допустимой задержки в рамках инфраструктуры PM QoS . Допустимая задержка — это значение в микросекундах, которое выражает, какую дополнительную задержку из-за простоя CPU драйвер или процесс пользовательского пространства может выдержать до ухудшения их производительности. cpuidle выбирает наименьшие значения среди всех драйверов и процессов и предотвращает переход регулятора в глубокие состояния покоя, если время входа/выхода слишком велико.
Это отлично подходит для модальных систем, где вход в глубокие состояния покоя полезен для экономии энергии, но вход в глубокие состояния покоя нецелесообразен во всех режимах.
Подводя итог
В этом материале рассмотрено, как работает cpuidle , а также способы настройки систем с использованием современных функций, основанных на schedutil и ориентированном на таймерные события (teo) регуляторе простоя CPU.
Рассмотрение было ограничено cpuidle и оборудованием, на котором он построен. Существует множество других направлений для изучения. Например, не рассмотрено, как runtime PM позволяет управлять энергопотреблением периферийных устройств. Даже сосредоточившись на CPU, остается многое, что можно сказать на такие темы, как управление температурой или балансировка нагрузки в SMP. Балансировка нагрузки особенно интересна на гетерогенных CPU, таких как пионерская технология big.LITTLE от Arm, поскольку она предоставляет возможность экономить энергию за счет миграции задач на более эффективные процессоры.
Пока же стоит отметить, что настройка управления питанием — это практический навык, требующий от разработчиков встраиваемых систем на Linux понимания требований и ограничений рабочей нагрузки. Основное внимание здесь уделено функциям, а не оборудованию. На самом деле, использованный в примерах ноутбук на Arm был выбран не потому, что он является отличным примером встраиваемой системы Linux, а потому, что было известно об отсутствии каких-либо NDA! Обзор собственного оборудования — отличный способ расширить полученные здесь знания. Сочетание знаний об инструментах ядра, рабочей нагрузки и платформы ставит в наилучшее положение для создания систем с передовым временем работы от аккумулятора и производительностью.
Выражаем свою благодарность источнику, с которого взята и переведена статья, сайту cnx-software.com.
Оригинал статьи вы можете прочитать здесь.



