試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

動的にCPUクロックや電圧を変更するcpufreqの概要とcpufreqdデーモンについて

Linuxカーネル*1には、CPUが持っている動的なクロック周波数や電圧(対応している場合)の変更機能を利用するためのcpufreqという仕組みがある。
(2014/11/14)本記事の内容は最新ではないため、まとめドキュメントの各セクションを参照。

  1. CPUドライバ
  2. カーネルの設定
  3. クロック周波数の決定
  4. governorの手動変更
  5. cpufreqに関する現在の各種状態の取得
  6. ondemand governorでの動作時において、CPUクロックを上げるCPU使用率のしきい値
  7. cpufreqdで実用的な動的クロック変更を行う
    1. 設定
    2. 設定のテスト
    3. プロファイルの手動変更

CPUドライバ

クロックや電圧の変更をする方法はCPUによって違うため、CPUの種類ごとにデバイスドライバが用意されている。cpufreqを使用するには、

  • 使用しているCPUがクロックや電圧の変更をする機能を持っていて、BIOSでも有効になっている*2
  • 使用しているCPUに合ったドライバ(例: acpi-cpufreq, powernow-k8)を読み込む*3

の両方が必要。
(2008/8/18)Linux 2.6.26の時点では

という選択を行うことになる。EIST未対応なPentium4ではp4-clockmodを使うこともでき、他のCPUでもドライバが用意されているものは存在する。
(2010/11/12)AMDのK10(Athlon II,Phenom II)世代のCPUもK8(Athlon 64など)世代と同様のpowernow-k8を用い、「k10」の付いたモジュール名にはなっていない。

カーネルの設定

ディストリ付属のカーネルであれば、cpufreq関連も全てモジュールになっている可能性が高い。自分で設定する場合は
http://www.gentoo.org/doc/ja/power-management-guide.xml#doc_chap2
を参考に。手元の環境(Athlon64)では

Power management options  --->
 [*] Power Management support
 (中略)
 ACPI (Advanced Configuration and Power Interface) Support  --->
  [*] ACPI Support
  (中略)
  <*>   Processor
  <*>     Thermal Zone
  (以下略)
 CPU Frequency scaling  --->
  [*] CPU Frequency scaling
  [ ]   Enable CPUfreq debugging
  <*>   CPU frequency translation statistics
  [ ]     CPU frequency translation statistics details
  Default CPUFreq governor (userspace)  --->
  <*>   'performance' governor
  <*>   'powersave' governor
  ---   'userspace' governor for userspace frequency scaling
  <*>   'ondemand' cpufreq policy governor
  <*>   'conservative' cpufreq governor
  ---   CPUFreq processor drivers
  <*>   AMD Opteron/Athlon64 PowerNow!
  < >   Intel Enhanced SpeedStep (deprecated) 
  < >   ACPI Processor P-States driver
  ---   shared options
  [ ]   /proc/acpi/processor/../performance interface (deprecated)

のようにしている(全て組み込み)。「Default CPUFreq governor」は、ユーザスペースにする。
(2008/6/23)Linux 2.6.24からは、既定のgovernorとして「ondemand」と「conservative」が使用できるようになった。

クロック周波数の決定

http://www.gentoo.org/doc/ja/power-management-guide.xml#doc_chap3
にあるように、

  • クロックや電圧を調節する際の動作モード「governor」の種類
  • クロック周波数の変動可能範囲(最大値: /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq 最小値: /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq)

の両方によって、クロック周波数が変化する(最終的な)ポリシーが決められる。後述のcpufreqdでは、この2つの組み合わせ*5を「プロファイル」として扱う。
(2009/8/2)範囲に関する記述を微調整

governorの種類と動作ポリシー
種類動作
ondemand負荷がかかるとクロックを上げ、負荷が下がるとクロックも下げる(値は急に大きく変動する)
conservative負荷がかかるとクロックを上げ、負荷が下がるとクロックも下げる(値はゆっくり段階的に変動する)
powersave負荷に関わらず、変動可能範囲内の最低のクロックで動作
performance負荷に関わらず、変動可能範囲内の最高のクロックで動作
(2008/9/3)conservativeに関しては、後述のcpufreqdの設定とともに「cpufreqの「conservative」governorについての覚え書き」で詳しく扱っている。
(2009/8/2)powersaveとperformanceの記述を微調整

governorの手動変更

cpufrequtilsパッケージのcpufreq-setコマンドで変更できる。

$ sudo cpufreq-set -g ondemand

cpufreqに関する現在の各種状態の取得

cpufrequtilsパッケージのcpufreqd-infoでコマンドで表示できる。

$ cpufreq-info
cpufrequtils 002: cpufreq-info (C) Dominik Brodowski 2004-2006
Report errors and bugs to linux@brodo.de, please.
analyzing CPU 0:
  driver: powernow-k8
  CPUs which need to switch frequency at the same time: 0
  hardware limits: 1000 MHz - 2.20 GHz
  available frequency steps: 2.20 GHz, 2.00 GHz, 1.80 GHz, 1000 MHz
  available cpufreq governors: ondemand, powersave, userspace, performance
  current policy: frequency should be within 1000 MHz and 1.80 GHz.
                  The governor "ondemand" may decide which speed to use
                  within this range.
  current CPU frequency is 1000 MHz.

この場合、

  • CPUが1GHzから2.2GHzまでをサポートしている
  • クロックの値は2.2GHz,2GHz,1.8GHz,1GHzの4段階で変更される
  • ondemand governorで動作している
  • 最大値と最小値のポリシー設定により、1GHzから1.8GHzの間で変動させている

ということが分かる。
(2008/8/18)「available cpufreq governors」では、利用可能なgovernorの一覧が表示される。手元の環境ではカーネルビルド設定でconservativeを外しているためにこれが表示されていないが、有効にしていれば表示される。

ondemand governorでの動作時において、CPUクロックを上げるCPU使用率のしきい値

/sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_thresholdの値まで負荷がかかると、更にクロック周波数を上げようとする。この値は、低すぎると省電力効果が薄れ(すぐクロックが上がるため)、高すぎると処理の体感速度が悪くなる(負荷が高いのにクロックが上がりにくいと処理が遅くなるため)ので、難しい。現在は65にしている。
この値を上書きすれば手動で変更もできるが、後述のcpufreqdでも設定できる。

cpufreqdで実用的な動的クロック変更を行う

cpufreqdデーモンは、複数の「プロファイル」と「ルール」を定義することで、CPUの負荷だけでなく、動作しているプログラムや、その他様々な情報*6により、高度な条件の作成ができ、システムの状態に適したクロック制御で、優れた省電力効果が得られる。*7

設定
手元の設定では、

  • 基本はondemand
  • クロックを上げるしきい値は65%
  • 最低クロックで快適に動作するが、CPU使用率が常に100%になるようなソフトウェア(一部のゲームなど)に対して、これが動作するとクロックを最低に下げるようにする*8
  • ルールからは使用しないが、手動で変更したいときのために、プロファイルは余計に作ってある

という程度のことしかしていない上、CPUクロックの値も、環境に合わせて調整する必要があるため、無駄にCPUを100%使用するアプリの対策以外は、あまり参考にならないかもしれない。あくまでも自分用の覚え書きということで貼っておく。

ファイル名: /etc/cpufreqd.conf

[General]
pidfile=/var/run/cpufreqd.pid
poll_interval=4
enable_remote=1
remote_group=wheel
verbosity=0
[/General]

[Profile]
name=ondemand low
minfreq=1000000
maxfreq=1800000
up_threshold=70
policy=ondemand
[/Profile]

[Profile]
name=ondemand mid
minfreq=1000000
maxfreq=2000000
up_threshold=70
policy=ondemand
[/Profile]

[Profile]
name=ondemand high
minfreq=1000000
maxfreq=2200000
up_threshold=70
policy=ondemand
[/Profile]

[Profile]
name=powersave low
minfreq=1000000
maxfreq=1000000
policy=powersave
[/Profile]

[Profile]
name=powersave mid
minfreq=1800000
maxfreq=1800000
policy=powersave
[/Profile]

[Profile]
name=performance
minfreq=2200000
maxfreq=2200000
policy=performance
[/Profile]

# 最低クロックで快適に動作するがCPU使用率100%のものに対してクロック下げ
[Rule]
name=throttle low
cpu_interval=0-100
programs=program1,program2,program3
profile=powersave low
[/Rule]

# 最低クロックよりは高いクロックが必要だが常に100%というわけではないもの
[Rule]
name=throttle mid-ondemand
cpu_interval=0-100
programs=program4
profile=ondemand low
[/Rule]

# 最低クロックよりは高いクロックが必要なもの(100%使用)に対してクロック下げ
[Rule]
name=throttle mid-fixed
cpu_interval=0-100
programs=program5
profile=powersave mid
[/Rule]

# デフォルトは最低クロックから最大クロックまで使用
[Rule]
name=default
cpu_interval=0-100
profile=ondemand high
[/Rule]

(2008/8/4)内容に関して、以下の修正を行った。

  • 「enable_plugins」の行は不要な上、書かないほうがよくなっているらしいため、外している
  • コメントの記号は正しくは「#」なので修正
  • 最低ではないクロックでの動作で、低負荷時にクロックを下げるもの(throttle mid-ondemand)と下げないもの(throttle mid-fixed)とを分けた

なお、これは設定例(参考)ということで、これをコピペしてそのまま使うことはできない。環境や運用ポリシーによって、値は変更する。


以下は設定上の覚え書き。

  • poll_intervalは、何秒ごとに状態を見て、ルールの変更を検討するかの間隔。3〜4秒が適当?
  • enable_pluginsで、情報を取得するプラグインをコンマ区切りで記述
  • enable_remoteを1にすると、remote_groupで指定したグループのメンバーがcpufreqd-setコマンドで、プロファイルを手動で変更できるようになる
  • minfreqとmaxfreqは「80%」のような、最大(定格)のクロック周波数に対するパーセンテージでも記述できる
  • up_thresholdは、前述の、クロックを上げるために必要なCPU使用率。プロファイルごとに決められる*9
  • cpu_interval指定では、ルール適用の条件となるCPU使用率の幅を書くのだが、上の例では特にクロック変更の動作には関係ない。「default」のルールがデフォルトで動作するようにするために書いてある
  • programs指定では、(動作していると)ルール適用の条件となるプログラムの実行ファイル名(例: blobwars)をコンマ区切りで書く
  • (2008/8/4)ルールを記述する順番には意味があり、優先される順番が変わるようだ。テスト中、意図した通りにルールが適用されない場合、ルール記述の順番を変えて試すと、うまく動くことがあるかもしれない

詳細は「man cpufreqd.conf」を参照。

設定のテスト
ルールが思った通りに適用されて、プロファイルが切り替えられているかなど、詳細なメッセージを表示しながら実行する形のテストを

$ sudo /usr/sbin/cpufreqd -D -V 7

のようにして行い、Ctrl+Cで止める。問題がなければ

$ sudo /etc/init.d/cpufreqd start

で開始。
(2008/8/4)-Vオプションの後ろの値はメッセージの詳細度で、必要に応じて6や5などの値で多少大まかなメッセージを見るようにすることもできる。
(2010/2/5)「cpufreqdの手動プロファイル/モード変更ツールを更新(Vala言語への移植,デーモン制御機能とテストツールの追加)」で作成したバージョン2(1.9)系のcpufreqd-iconではこのテストをGUI上で簡単に行えるようにした。

プロファイルの手動変更
プロファイルは、ルールに基づいて、ルールの記述内に指定されたプロファイルが自動的に選択されて切り替わるのだが、手動でこれを変更するには、上記enable_remoteとremote_groupの設定をした上で、

$ cpufreqd-set manual

マニュアルモードに切り替え、更に、プロファイルの番号を指定する。番号はcpufreqd-getコマンドで

$ cpufreqd-get
socket I'll try to connect: /tmp/cpufreqd-xxxxxx/cpufreqd

Name (#1):      ondemand-low
Governor:       ondemand
Min freq:       1000000
Max freq:       1800000

Name (#2):      ondemand-mid
Governor:       ondemand
Min freq:       1000000
Max freq:       2000000

Name (#3):      ondemand-high *
Governor:       ondemand
Min freq:       1000000
Max freq:       2200000

Name (#4):      powersave-low
Governor:       powersave
Min freq:       1000000
Max freq:       1000000

Name (#5):      powersave-mid
Governor:       powersave
Min freq:       1800000
Max freq:       1800000

Name (#6):      performance
Governor:       performance
Min freq:       2200000
Max freq:       2200000

のように一覧を表示し、「#」の後ろの番号を見て指定する。現在選択されているプロファイル(上の例では#3)には、後ろに「*」が付いている。例として、ondemandの1GHz-1.8GHz動作にする「#1」を選択する場合は

$ cpufreqd-set 1

を実行する。手動プロファイル変更(マニュアルモード)から自動プロファイル変更(ダイナミックモード)に戻すには

$ cpufreqd-set dynamic

を実行。
(2008/8/4)cpufreqdのバージョン2.2系では、選択されているプロファイルの表示は

Name (#1):      ondemand low
Governor:       ondemand
Min freq:       1000000
Max freq:       1800000

Name (#2):      ondemand mid
Governor:       ondemand
Min freq:       1000000
Max freq:       2000000

Name (#3):      ondemand high
Active on CPU#: 0
Governor:       ondemand
Min freq:       1000000
Max freq:       2200000
(以下略)

のように、名前の下にCPU番号で表示されるようになっている。

使用したバージョン:

  • cpufreqd-2.1.1, 2.2.1

*1:2.6系から利用可能

*2:以前使用していたPentium4では、BIOS設定でクロック変更機能に関する項目がなかったが、p4-clockmodドライバでcpufreqは使えていた

*3:モジュールの場合、modprobeで読み込み、組み込みの場合は何もしない

*4:Athlon世代はpowernow-k7K6世代はpowernow-k6

*5:実際にはそれ以外の要素も追加できるが、必須なのはこの2つと識別名だけで、governorは「policy」、範囲は「minfreq」と「maxfreq」

*6:センサ経由で取得する温度や、バッテリー動作などによる条件も作れるが、ここでは取り上げない

*7:センサ温度やバッテリーなどを設定に組み込むと、更に大きな効果が得られる

*8:これをしないと、無駄にクロックが最大になって、電力の大幅な損失(無駄)になる

*9:conservative指定時には、クロックを下げるときのしきい値「down_threshold」も指定できる