Управляем частотой CPU в ОС FreeBSD

12th Июль 2010 | Метки: , ,
Опубликовал: Dmitriy [dk] Kalinin

В интернете можно найти все, ну почти все. Проблема в том — что просто не знаешь чего искать то.
Так и с этой темой.

Как то обратил внимание сколько потребляется кВт/ч в месяц, сумма не очень понравилась, и решил с этим хоть как-то бороться. Жесткие диски работают постоянно, Westeng Digital серия Green, как заявлено производителем — с пониженным энергопотреблением. В общем — за счет них не особо сэкономишь. Видео-карта …, тоже нет механизмов регулирования. Сетевая — такая же беда. И вот добираемся до процессора. Как известно, все достаточно современные процессоры позволяют регулировать свою частоту, как следствие при понижении частоты — энергопотребление уменьшается, при увеличении — соответственно увеличивается.

В ОС FreeBSD существует драйвер, для управления частотой процессора — это cpufreq.

Бегло окидываем взглядом man по нему и получаем след. средства управления этим драйвером через sysctl:

dev.cpu.%d.freq
Current active CPU frequency in MHz.
dev.cpu.%d.freq_levels
Currently available levels for the CPU (frequency/power usage).
Values are in units of MHz and milliwatts.
 
dev.DEVICE.%d.freq_settings
Currently available settings for the driver (frequency/power
usage).  Values are in units of MHz and milliwatts.  This is
helpful for understanding which settings are offered by which
driver for debugging purposes.
 
debug.cpufreq.lowest
Lowest CPU frequency in MHz to offer to users.  This setting is
also accessible via a tunable with the same name.  This can be
used to disable very low levels that may be unusable on some sys‐
tems.
 debug.cpufreq.verbose
Print verbose messages.  This setting is also accessible via a
tunable with the same name.

Ага, что же мы получили:
dev.cpu.%d.freq — текущая частота процессора;
dev.cpu.%d.freq_levels — доступные настройки для драйвера (частота/мощность). Частота в МГЦ, мощность в мВт;
dev.DEVICE.%d.freq_settings, debug.cpufreq.lowest, debug.cpufreq.verbose — отладочные параметры, про них позже.

Если верить описанию — на процессору можно установить любую частоту из списка dev.cpu.%d.freq_levels. Частота устанавливается через системную переменную dev.cpu.%d.freq, так же она отображает текущую частоту процессора.
Ну что ж, это функционал устраивает, приступаем к настройке.

Установка драйвера

Здесь все элементарно, устанавливаем модуль ядра и подгружаем его:

[18:08 dk@mira ~]> cd /usr/src/sys/modules/cpufreq/
[18:13 dk@mira /usr/src/sys/modules/cpufreq]> sudo make
...
[18:13 dk@mira /usr/src/sys/modules/cpufreq]> sudo make install cleandir
install -o root -g wheel -m 555   cpufreq.ko /boot/kernel
kldxref /boot/kernel
rm -f export_syms cpufreq.ko cpufreq.kld ichss.o est.o hwpstate.o p4tcc.o powernow.o opt_acpi.h acpi_if.h pci_if.h bus_if.h cpufreq_if.h device_if.h
rm -f @ machine
rm -f .depend GPATH GRTAGS GSYMS GTAGS

Загружаем модуль и проверяем настройки драйвера:

[18:14 dk@mira /usr/src/sys/modules/cpufreq]> sudo kldload cpufreq
[18:15 dk@mira /usr/src/sys/modules/cpufreq]> kldstat -v | grep cpufreq
151 cpu/cpufreq
10    1 0xffffffff8090f000 e7d8     cpufreq.ko (/boot/kernel/cpufreq.ko)
[18:15 dk@mira /usr/src/sys/modules/cpufreq]> sysctl -a|grep freq
kern.acct_chkfreq: 15
kern.timecounter.tc.i8254.frequency: 1193182
kern.timecounter.tc.ACPI-fast.frequency: 3579545
kern.timecounter.tc.HPET.frequency: 14318180
kern.timecounter.tc.TSC.frequency: 1866677939
debug.cpufreq.lowest: 0
debug.cpufreq.verbose: 0
machdep.acpi_timer_freq: 3579545
machdep.tsc_freq: 1866677939
machdep.i8254_freq: 1193182
dev.cpu.0.freq: 1867
dev.cpu.0.freq_levels: 1867/22464 1633/19656 1600/22464 1400/19656 1200/16848 1000/14040 800/11232 600/8424 400/5616 200/2808
dev.acpi_perf.0.freq_settings: 1867/22464 1600/22464
dev.cpufreq.0.%driver: cpufreq
dev.cpufreq.0.%parent: cpu0
dev.cpufreq.1.%driver: cpufreq
dev.cpufreq.1.%parent: cpu1
dev.p4tcc.0.freq_settings: 10000/-1 8750/-1 7500/-1 6250/-1 5000/-1 3750/-1 2500/-1 1250/-1
dev.p4tcc.1.freq_settings: 10000/-1 8750/-1 7500/-1 6250/-1 5000/-1 3750/-1 2500/-1 1250/-1

Диапазон частот от 1867МГц до 200МГц, при этом потребляемая мощность может меняться от 22,464Вт до 2,808Вт. При максимальной частоте в 1867 МГц потребляемая мощность составит 22,464Вт, а при минимальной частоте 200МГц всего 2,808Вт — что почти в 10 раз меньше!!!
Разрешаем драйверу загружаться вместе с системой, для этого в файл /boot/loader.conf добавляем следующею строку:

cpufreq_load="yes"

Пробуем драйвер

Драйвер загружен в память, список частот есть — теперь самое время его опробовать. Поменяем частоту процессора с максимальной до минимальной и обратно:

[18:23 root@mira ~]# sysctl dev.cpu.0.freq=200
dev.cpu.0.freq: 1867 -> 200
[18:23 root@mira ~]# sysctl  dev.cpu.0.freq
dev.cpu.0.freq: 200
[18:24 root@mira ~]# sysctl dev.cpu.0.freq=1867
dev.cpu.0.freq: 200 -> 1867
[18:24 root@mira ~]# sysctl dev.cpu.0.freq
dev.cpu.0.freq: 1867

Вроде работает, можно двигаться дальше.

Управляем частотой процессора в зависимости от нагрузки

Первая мысль, которая пришла в голову — это написать свой скрипт, который в течении промежутка времени будет собирать статистику по загрузке процессора, и если загрузки нет — то просто понижать частоту до следующей ступени. А если загрузка есть, и активная — то наоборот, повышать до следующей ступени.
Но после детального прочтения документации по cpufreq вышел на службу powerd, которая занимается именно этим. Итак, какие параметры есть у этой службы:

DESCRIPTION
The powerd utility monitors the system state and sets various power con‐
trol options accordingly.  It offers four modes (maximum, minimum, adap‐
tive and hiadaptive) that can be individually selected while on AC power
or batteries.  The modes maximum, minimum, adaptive and hiadaptive may be
abbreviated max, min, adp, hadp.
Maximum mode chooses the highest performance values.  Minimum mode
selects the lowest performance values to get the most power savings.
Adaptive mode attempts to strike a balance by degrading performance when
the system appears idle and increasing it when the system is busy.  It
offers a good balance between a small performance loss for greatly
increased power savings.  Hiadaptive mode is like adaptive mode, but
tuned for systems where performance and interactivity are more important
than power consumption.  It increases frequency faster, reduces the fre‐
quency less aggressively and will maintain full frequency for longer.
The default mode is adaptive for battery power and hiadaptive for the
rest.
 
The powerd utility recognizes the following runtime options:
 
-a mode     Selects the mode to use while on AC power.
 
-b mode     Selects the mode to use while on battery power.
 
-i percent  Specifies the CPU load percent level when adaptive mode
should begin to degrade performance to save power.  The
default is 50% or lower.
 
-n mode     Selects the mode to use normally when the AC line state is
unknown.
 
-p ival     Specifies a different polling interval (in milliseconds) for
AC line state and system idle levels.  The default is 250 ms.
 
-P pidfile  Specifies an alternative file in which the process ID should
be stored.  The default is /var/run/powerd.pid.
 
-r percent  Specifies the CPU load percent level where adaptive mode
should consider the CPU running and increase performance.
The default is 75% or higher.
 -v          Verbose mode.  Messages about power changes will be printed
to stdout and powerd will operate in the foreground.

Как следует из описания — поддерживается 4 режима работы:
— max (maximum) — выбираются максимальные настройки производительности (установит макс. частоту процессора);
— min (minimum) — выбираются минимальные настройки производительности (установит минимальную частоту процессора);
— adp(adaptive) — адаптивный, понижает частоту при простое, и увеличивает при появлении нагрузки;
— hadp (hiadaptive) — аналогичен адаптивному режиму, но упор делается на производительность, в ущерб энергопотреблению. Частоту процессора увеличивает быстрее чем понижает.
Первые два режима нам не интересны, ибо max — это и без драйвера включен, min — все время держать минимальную частоту совсем не интересно.
Остается два режима, adp и hadp. Вот их и посмотрим, для это запускаем powerd по очереди в каждом режиме:

[18:38 root@mira ~]# powerd -v -a adp
powerd: unable to determine AC line status
load  16%, current freq 1867 MHz ( 0), wanted freq 1633 MHz
changing clock speed from 1867 MHz to 1633 MHz
load  14%, current freq 1633 MHz ( 1), wanted freq 1428 MHz
changing clock speed from 1633 MHz to 1600 MHz
powerd: error setting CPU frequency 1600: Invalid argument
load  18%, current freq 1600 MHz ( 2), wanted freq 1249 MHz
changing clock speed from 1600 MHz to 1400 MHz
load  26%, current freq 1400 MHz ( 3), wanted freq 1092 MHz
changing clock speed from 1400 MHz to 1200 MHz
powerd: error setting CPU frequency 1200: Invalid argument
load  24%, current freq 1200 MHz ( 4), wanted freq  955 MHz
changing clock speed from 1200 MHz to 1000 MHz
powerd: error setting CPU frequency 1000: Invalid argument
load  26%, current freq 1000 MHz ( 5), wanted freq  835 MHz
load  30%, current freq 1000 MHz ( 5), wanted freq  730 MHz
changing clock speed from 1000 MHz to 800 MHz
powerd: error setting CPU frequency 800: Invalid argument
load  29%, current freq  800 MHz ( 6), wanted freq  638 MHz
load  26%, current freq  800 MHz ( 6), wanted freq  558 MHz
changing clock speed from 800 MHz to 600 MHz
powerd: error setting CPU frequency 600: Invalid argument
load  45%, current freq  600 MHz ( 7), wanted freq  488 MHz
load  20%, current freq  600 MHz ( 7), wanted freq  427 MHz
load   9%, current freq  600 MHz ( 7), wanted freq  373 MHz
changing clock speed from 600 MHz to 400 MHz
powerd: error setting CPU frequency 400: Invalid argument
load  38%, current freq  400 MHz ( 8), wanted freq  326 MHz
load  30%, current freq  400 MHz ( 8), wanted freq  285 MHz
load  35%, current freq  400 MHz ( 8), wanted freq  249 MHz
load  17%, current freq  400 MHz ( 8), wanted freq  217 MHz
load  30%, current freq  400 MHz ( 8), wanted freq  200 MHz
changing clock speed from 400 MHz to 200 MHz
powerd: error setting CPU frequency 200: Invalid argument
load  45%, current freq  200 MHz ( 9), wanted freq  200 MHz
^Ctotal joules used: 51.948
[18:40 root@mira ~]# powerd -v -a hadp
powerd: unable to determine AC line status
load  12%, current freq 1867 MHz ( 0), wanted freq 1808 MHz
load  11%, current freq 1867 MHz ( 0), wanted freq 1751 MHz
load   4%, current freq 1867 MHz ( 0), wanted freq 1696 MHz
load  15%, current freq 1867 MHz ( 0), wanted freq 1643 MHz
load  11%, current freq 1867 MHz ( 0), wanted freq 1591 MHz
changing clock speed from 1867 MHz to 1600 MHz
powerd: error setting CPU frequency 1600: Invalid argument
load  15%, current freq 1600 MHz ( 2), wanted freq 1541 MHz
load  17%, current freq 1600 MHz ( 2), wanted freq 1492 MHz
load  17%, current freq 1600 MHz ( 2), wanted freq 1445 MHz
load  22%, current freq 1600 MHz ( 2), wanted freq 1399 MHz
changing clock speed from 1600 MHz to 1400 MHz
load  19%, current freq 1400 MHz ( 3), wanted freq 1355 MHz
load  20%, current freq 1400 MHz ( 3), wanted freq 1312 MHz
load   9%, current freq 1400 MHz ( 3), wanted freq 1271 MHz
load  23%, current freq 1400 MHz ( 3), wanted freq 1231 MHz
load  23%, current freq 1400 MHz ( 3), wanted freq 1192 MHz
changing clock speed from 1400 MHz to 1200 MHz
powerd: error setting CPU frequency 1200: Invalid argument
load  18%, current freq 1200 MHz ( 4), wanted freq 1154 MHz
load  26%, current freq 1200 MHz ( 4), wanted freq 1154 MHz
load  15%, current freq 1200 MHz ( 4), wanted freq 1117 MHz
^Ctotal joules used: 87.750

Как и следовало из описания — hadp стремиться занять максимальную частоту, но при простое уменьшает. adp — симметричный баланс, растет также как и падает. Что из этого следует? А следует вот что: в режиме hadp — процессор максимально быстро выйдет на рабочую частоту, т.е. фактические одиночный всплеск нагрузки заставит ворочаться процессор на максимальной частоте, в то время как частота процессора при простое будет понижаться не так оперативно. В режиме adp — будет симметричное понижение/повышение частоты процессора — т.е. он одинаково медленно будет опускать частоту и поднимать частоту .
Выбор режима должен каждый выбирать для себя, это дело вкуса. Хотите чтобы процессор выходил на максимальную частоту предельно быстро — то это hadp, но потребление будет выше. Если не обломаться, и подождать несколько секунд до выхода на максимальную частоту — то это режим adp.
Лично для моих нужд adp хватает за глаза.
Добавочно можно регулировать переключение частот параметрами -r и -i:
-r — указывает порог нагрузки, при котором следует повышать частоту. По умолчанию — 75% и больше. Т.е. при нагрузке в 75% и выше частота процессора будет повышаться;
-i — указывает порог нагрузки, при котором следует понижать частоту. По умолчанию — 50% и меньше. Т.е. при нагрузке 50% и ниже — частота процессора будет понижаться.
Под мои нужды, как я и указывал выше — реактивной реакции не надо, могу и подождать некоторое время. Для этого указываю — что увеличивать частоту при нагрузке в 90% и выше.
Проверяем:

[18:51 root@mira ~]# powerd -a adp -r 90 -v
...
load  26%, current freq  200 MHz ( 9), wanted freq  200 MHz
load  70%, current freq  200 MHz ( 9), wanted freq  200 MHz
load 150%, current freq  200 MHz ( 9), wanted freq  400 MHz
changing clock speed from 200 MHz to 400 MHz
powerd: error setting CPU frequency 400: Invalid argument
load 129%, current freq  400 MHz ( 8), wanted freq  800 MHz
changing clock speed from 400 MHz to 800 MHz
powerd: error setting CPU frequency 800: Invalid argument
load  73%, current freq  800 MHz ( 6), wanted freq  800 MHz
load  33%, current freq  800 MHz ( 6), wanted freq  700 MHz
load 113%, current freq  800 MHz ( 6), wanted freq 1400 MHz
changing clock speed from 800 MHz to 1400 MHz
load  69%, current freq 1400 MHz ( 3), wanted freq 1400 MHz
load  29%, current freq 1400 MHz ( 3), wanted freq 1225 MHz
load  35%, current freq 1400 MHz ( 3), wanted freq 1071 MHz
changing clock speed from 1400 MHz to 1200 MHz
powerd: error setting CPU frequency 1200: Invalid argument
load  12%, current freq 1200 MHz ( 4), wanted freq  937 MHz
changing clock speed from 1200 MHz to 1000 MHz
powerd: error setting CPU frequency 1000: Invalid argument
load  20%, current freq 1000 MHz ( 5), wanted freq  819 MHz
load  39%, current freq 1000 MHz ( 5), wanted freq  716 MHz
changing clock speed from 1000 MHz to 800 MHz
powerd: error setting CPU frequency 800: Invalid argument
load  26%, current freq  800 MHz ( 6), wanted freq  626 MHz
load  25%, current freq  800 MHz ( 6), wanted freq  547 MHz
changing clock speed from 800 MHz to 600 MHz
powerd: error setting CPU frequency 600: Invalid argument
load  25%, current freq  600 MHz ( 7), wanted freq  478 MHz
...

Вполне приемлемый результат. Что показывают эти цифры: после выхода процессора на минимальную частоту в 200МГц была дана нагрузка в течении секунды, что видно в плавном повышении до 1400МГц, а после исчезновения нагрузки — плавное понижение. Каждая строчка — это период в 250мс, который, кстати, тоже можно менять с помощью параметра -p. Попробуем уменьшить период до 100мс:

[18:57 root@mira ~]# powerd -a adp -r 90 -p 100 -v
 

Видно, что тестовой нагрузки в одну секунду хватило чтоб вывести процессор на максимальную частоту, причем довольно быстро — за 700мс (количество строк после 200МГц * 100мс). В то время как при интервале в 250мс потребовалась 9 строк и выход был на частоту в 1400МГц.
Пожалуй, эти настройки и оставлю. Но, эти параметры должен каждый подбирать под свои задачи!
Добавляем в /etc/rc.conf запуск powerd и параметры для запуска:

powerd_enable="yes"
powerd_flags="-a adp -p 100 -r 90"

Ну и запускаем его:

[19:02 root@mira /etc]# /etc/rc.d/powerd start
Starting powerd.

Все! Об эффективности этого метода можно будет теперь по следующему счету за электричество.

  1. denis
    16th Октябрь 2010 в 14:33

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

  2. sergey
    27th Март 2011 в 19:38

    denis :видео выдернуть из сервака, а кол-во винтов держать не выше трех,
    а то проблемы с питальниками начинаются.
    как-то было пять винтов – через пару месяцев/полгода накрылся питальник :)

    У меня лично есть сервер с 12 установленными HDD и все прекрасно работает вот уже 2 года. Единственное но, БП для него покупал на 650Вт. С более слабым БП диски стартуют неуверенно, то паркуются, то выпадают из массива.

  3. sergey
    27th Март 2011 в 19:40

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

  4. Yaakov Tooth
    4th Апрель 2011 в 17:20

    О! Спасибо, от нечего делать тоже ковырял sysctl’ы на трёх серверах домашних. Из-за счетов на электричество. Пока костыли писал — прочитал статью.

    По одной и той же строчке в rc.local и профит.

    Автор, гран мерси и респект в карму! :)

  5. Yaakov Tooth
    4th Апрель 2011 в 17:24

    denis :видео выдернуть из сервака, а кол-во винтов держать не выше трех,
    а то проблемы с питальниками начинаются.
    как-то было пять винтов – через пару месяцев/полгода накрылся питальник :)

    Массив с шестью винтами, Б/П ватт на 500, полёт три года. ;)

Вы должны авторизоваться для отправки комментария.