Pull to refresh

Processor scaling под FreeBSD, или экономим мегагерцы

Выкопал тут в одном из номеров жернала BSD magazine статью про возможность управлять частотой процессора во FreeBSD. Информация меня приколола и после ряда экспериментов на натуре решил статью перевести.

Slawomir Wojciech Wojtczak (имя автора транскрибировать я не рискнул).

FreeBSD, как и многие другие современные ОС семейства Unix предлагают возможность управления частотой процессора для уменьшения потребляемой процессором электроэнергии и тепловыделения (что косвенно также снижает потребление энергии).

В сравнении с другими системами, такими как Solaris или семейство Linux'ов, которые в точности следуют определёнными фирмой Intel C- и P-состояниями (C-states and P-states) процессора, FreeBSD пошла немножко дальше, и даёт возможность пользователю установить любую частоту процессора, на которой этот процессор в состоянии работать. Это может несколько сбивать толку, но всё станет ясно после прочтения следующего абзаца.

Давайте посмотрим, какие частоты Intel нам рекомендует для использования в процессоре T7300 2 ГГц: 800, 1200, 1600, 2000 МГц. Эти «ступеньки» частот доступны в упомянутых выше операционных системах, но FreeBSD предлагает следующий набор частот на этом же самом процессоре: 150, 300, 450, 600, 750, 900, 1050, 1200, 1400, 1600, 1750, 2000, что означает более широкие возможности в энергосбережении и бОльшую гибкость при выборе желаемой частоты. В случае использования одного и того же процессора Intel E6320, который, конечно же, поддерживает технологию Intel SpeedStep, Solaris или Linux предлагают использовать частоту 1600 или 1866 МГц, тогда как FreeBSD может начать с 250 МГц…

Включаем

Демон FreeBSD, который называется powerd(8), и отвечает за управление частотой процессора, по умолчанию отключён. Чтобы включить его при прочих настройках по умолчанию (которые довольно неплохи, кстати), нужно проделать следующие действия: добавить строку powerd_enable=«YES» в файл /etc/rc.conf, и, собственно, запустить сам демон:

box# /etc/rc.d/powerd start
Starting powerd.
box#


Проверим, действительно ли powerd(8) запустился:
box# pgrep powerd
893
box#


Для управления частотой нужно, чтобы ядро было скомпилировано с указанием опции cpufreq (которая по умолчанию включена в ядре FreeBSD, начиная с версии 7.1-RELEASE), либо должен быть загружен модуль cpufreq, если ядро было собрано без указания этой опции.

Вы можете сконфигурировать демон powerd(8) переключаться между более высокой и более низкой частотами процессора, в зависимости от текущей загрузки процессора, причём если вас не устраивают пороги переключения частот по умолчанию, вы можете задать свои. Делается это с помощью задания соответствующих значений для параметра powerd_flags в файле /etc/rc.conf. За подробностями можно обратиться к странице руководства man powerd.

powerd_fags="-i 85 -r 60 -p 100"

Итак, мы запустили демон powerd(8), теперь он управляет частотой нашего процессора. Чтобы посмотреть, в каких пределах powerd(8) может менять частоту процессора, нужно выполнить команду:

box# sysctl dev.cpu.0.freq_levels
dev.cpu.0.freq_levels: 2000/31000 1750/27125 1600/22000 1400/19250 1200/13000 1050/11375 900/9750 750/8125 600/6500 450/4875 300/3250 150/1625
box#


И, конечно же, мы можем выключить powerd(8), и установить желаемую частоту вручную, типа того:

box# /etc/rc.d/powerd stop
Stopping powerd.
box# sysctl dev.cpu.0.freq=450
dev.cpu.0.freq: 2000 -> 450
box#


Итак, подведём итоги: модуль ядра cpufreq позволяет нам устанавливать другие частоты работы процессора, а не только те, что предусмотрены в процессоре по умолчанию, и демон powerd(8) может автоматически менять частоту процессора в зависимости от текущей загрузки CPU, что позволяет экономить энергию.

Устанавливаем минимальную частоту

Мы можем установить минимальную частоту, которую нам бы хотелось, чтобы powerd(8) использовал. Для этого потребуется изменить значение параметра sysctl, который называется debug.cpufreq.lowest. Также можно прописать изменение этого параметра в файле /boot/loder.conf, чтобы это изменение стало постоянным и автоматически включалось после перезагрузки системы. Но можно минимальную частоту установить и без перезагрузки, для этого придётся всего лишь перезапустить powerd(8), чтобы он узнал о том, что минимальная частота установлена другая (см. Listing 1):

Listing 1. Устанавливаем минимальную частоту.

box# sysctl dev.cpu.0.freq
dev.cpu.0.freq: 150
box# sysctl debug.cpufreq.lowest
debug.cpufreq.lowest: 0
box# sysctl debug.cpufreq.lowest=450
debug.cpufreq.lowest: 0 -> 450
box# /etc/rc.d/powerd restart
Stopping powerd.
Starting powerd.
box# sysctl dev.cpu.0.freq
dev.cpu.0.freq: 450
box#


Устанавливаем максимальную частоту

Некоторые ноутбуки слегка перегреваются, когда их процессоры работают на максимальной скорости. Потребление энергии также достаточно велико, когда используется максимальная частота процессора. По умолчанию FreeBSD не имеет средств установить максимальную частоту процессора, но патч авторства Бориса Кочергина позволяет установить максимальную частоту процессора (highest step) (см. Листинг 2). Чтобы применить этот патч, нужно проделать несколько простых операций:

box# cd /usr/src/sys/kern
box# patch < /path/to/patch
box#


Listing 2. Патч, позволяющий установить ограничение по максимальной частоте.

--- kern_cpu.c.orig 2008-11-08 13:12:24.000000000 -0500
+++ kern_cpu.c 2008-11-08 10:33:18.000000000 -0500
@@ -131,12 +131,16 @@
DRIVER_MODULE(cpufreq, cpu, cpufreq_driver, cpufreq_dc, 0, 0);

static int cf_lowest_freq;
+static int cf_highest_freq;
static int cf_verbose;
TUNABLE_INT("debug.cpufreq.lowest", &cf_lowest_freq);
+TUNABLE_INT("debug.cpufreq.highest", &cf_highest_freq);
TUNABLE_INT("debug.cpufreq.verbose", &cf_verbose);
sysctl_NODE(_debug, OID_AUTO, cpufreq, CTLFLAG_RD, NULL, "cpufreq
debugging");
sysctl_INT(_debug_cpufreq, OID_AUTO, lowest, CTLFLAG_RW, &cf_lowest_freq,
1,
"Don't provide levels below this frequency.");
+sysctl_INT(_debug_cpufreq, OID_AUTO, highest, CTLFLAG_RW, &cf_highest_
freq, 1,
+ "Don't provide levels above this frequency.");
sysctl_INT(_debug_cpufreq, OID_AUTO, verbose, CTLFLAG_RW, &cf_verbose, 1,
"Print verbose debugging messages");

@@ -295,6 +299,14 @@
goto out;
}

+ /* Reject levels that are above our specifed threshold. */
+ if (cf_highest_freq > 0 && level->total_set.freq > cf_highest_freq)
{
+ CF_DEBUG("rejecting freq %d, greater than %d limit\n",
+ level->total_set.freq, cf_highest_freq);
+ error = EINVAL;
+ goto out;
+ }
+
/* If already at this level, just return. */
if (cpufreq_CMP(sc->curr_level.total_set.freq, level->total_set.freq)) {
CF_DEBUG("skipping freq %d, same as current level %d\n",
@@ -617,8 +629,13 @@
continue;
}

- /* Skip levels that have a frequency that is too low. */
- if (lev->total_set.freq < cf_lowest_freq) {
+ /*
+ * Skip levels that have a frequency that is too low or too
+ * high.
+ */
+ if (lev->total_set.freq < cf_lowest_freq ||
+ (cf_highest_freq > 0 &&
+ lev->total_set.freq > cf_highest_freq)) {
sc->all_count—;
continue;
}


Теперь нужно пересобрать ядро (или только модуль cpufreq, если вы не включали эту опцию в ядре). За подробностями в этом процессе можно обратиться к FreeBSD Handbook. После перезагрузки системы или модуля cpufreq в sysctl появится параметр debug.cpufreq.highest, который можно использовать для установления максимальной частоты процессора с помощью powerd(8). Как и в случае с минимальной частотой, наилучшим местом для установления значения максимальной частоты, является файл /boot/loader.conf. После того, как вы установите максимальную и минимальную частоты, список доступных частот, которые выводятся при опросе параметра dev.cpu.0.freq_levels, будет ограничен этими значениями:

box# sysctl dev.cpu.0.freq_levels
dev.cpu.0.freq_levels: 1200/13000 1050/11375 900/9750 750/8125 600/6500
box#


В приведённой ниже таблице можно посмотреть таблицу распределения потребления энергии процессором T7300, в зависимости от частоты. Все измерения проведены внешним прибором для измерения мощности. Ноутбук работал только от сети, потребление при работе от батареи не измерялось. Конечно же, процессор в момент измерения был загружен на 100% 4-мя процессами python, вычисляющими значение 999999999999 в степени 999999999999 (см. Table 1).

image

Похоже, что частота 1200 МГц — наилучшая для использования на данном типе процессоров, все более высокие частоты резко увеличивают энергопотребление.

Я также измерил потребление в режиме простоя процессора, но отличие в энергопотреблении даже между крайними частотами 150 Гц и 2000 МГц слишком невелико — около 3 ватт, из чего следует, что важнейшим критерием является потребление процессора в режиме максимальной нагрузки.

Используем C-состояния (C-states)

Теперь мы знаем, как изменять частоту, с которой работает процессор. Пришло время научиться изменять C-состояния, которые определяют разные уровни «засыпания» процессора (точнее, его ядер), когда он какое-то время находится в состоянии простоя. Ниже приведена таблица, в которой перечислены все С-состояния, которые доступны для процессора Intel T7300. Более новые версии платформы Montevina имеют даже больше C-состояний, с ещё более глубокой степенью «засыпания» (см. Table 2).
image

Чтобы узнать, какие С-состояния поддерживаются и доступны из FreeBSD для вашего типа процессора, выполните следующую команду:

box# sysctl dev.cpu.0.cx_supported
dev.cpu.0.cx_supported: C1/1 C2/1 C3/57
box#

Видно, что в нашем случае FreeBSD поддерживает состояния с C0 до C3, и можно получить/установить самое «низкое» C-состояние для каждого ядра. Делается это следующим образом:

box# sysctl dev.cpu.0.cx_lowest
dev.cpu.0.cx_lowest: C1
box# sysctl dev.cpu.0.cx_lowest=C3
dev.cpu.0.cx_lowest: C1 -> C3
box# sysctl dev.cpu.1.cx_lowest
dev.cpu.1.cx_lowest: C1
box# sysctl dev.cpu.1.cx_lowest=C2
dev.cpu.1.cx_lowest: C1 -> C2
box#

Существует, правда, одна тонкость, которую вы должны знать про C-состояния. Если вы переведёте процессор в наиболее «глубокое» С-состояние (в приведённом примере это состояние C3), тачпад ноутбука будет слегка притормаживать, прежде чем его можно будет использовать (задержка будет составлять примерно 1 секунду), что может с течением времени начать сильно раздражать. Решением будет перевод одного ядра процессора в состояние, которое обеспечит меньшую задержку для «просыпания». В данном примере это состояние C2. Все остальные ядра можно перевести в состояние наиболее «глубокого» сна из доступных состояний, чтобы обеспечить максимально возможную экономию энергии.

Чтобы сохранить все эти изменения и после перезагрузки, как обычно, можно воспользоваться файлом /boot/loader.conf. Можно также посмотреть статистику использовать C-состояний следующей командой:

box# sysctl dev.cpu.0.cx_usage
dev.cpu.0.cx_usage: 0.00% 0.04% 99.95%
box# sysctl dev.cpu.1.cx_usage
dev.cpu.1.cx_usage: 0.00% 100.00%
0.00%
box#

Другие параметры

Можно также понизить частоту таймера ядра, изменяя параметр sysctl(8) kern.hz со значения по умолчанию 1000, например, до 100. Но это можно сделать только на этапе загрузки системы, так что нужно добавить строчку kern.hz=100 в файл /boot/loader.conf и перезагрузиться. Предполагается, что в будущем значение kern.hz, равное 100, станет дефолтным, но мы, похоже, не увидим этого до 8.0-RELEASE (к слову, в 8.0-RELEASE значение kern.hz таки равно 1000). Ещё можно сделать одну штуку, которая сильно зависит от процессора — это монтировать файловые системы с опцией noatime.

И несколько слов для владельцев процессоров AMD. FreeBSD также поддерживает возможность управления частотами для этих процессоров, используя технологию AMD Cool'n'Quiet. Она работает точно так же, как и описано для процессоров Intel в этой статье.

Ну, вот, собственно, и всё, что касается управления частотой процессора во FreeBSD. Если вы используете FreeBSD на своём компьютере, надеюсь, эта информация окажется для вас полезной.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.