ここ数日、急に、暑くなってきました。
あぁ、暑い、あつい、熱い、といえば、パソコンも暑くなる原因の1つ。ひどいときには、ファンから、まるでドライヤーのように熱風が吹き出していたり・・・
パソコンが何十台もある部屋があるんですが、1台から出る熱が少なくても、台数が増えてくると、たまりません。パソコンから出た熱をさますために、クーラーががんばるので、クーラーの電力消費量も増えますし、そもそも、熱の発生源であるパソコン自体が、熱の分だけ電力を消費しているわけです。電気を大切にね、と。
というようなわけで、最近のパソコンには、とくになんの仕事もしていないときは、CPUのクロック周波数を低くしたり、CPUの電源電圧を下げたりすることで、電力消費量を減らす仕組みが用意されています。
こういう機能は、一見、バッテリで動くノートパソコンだけの専用機能かと思いがちですが、実は、最近のデスクトップパソコンの多くでも、利用可能になっています。
さてさて、FreeBSDの場合、そのへんの仕組みは、どうなってんのよ?と思い、調べてみました。
わかったこと。
インストールしたまんまの状態では、何もやってません。
おしまい。
なんと、そうだったんですかっ!?
一応、現在の最新バージョンである、FreeBSD 5.5、FreeBSD 6.1の両方で、機能は用意されているのですが、使うように設定しない限り、機能は無効化されています。
というわけで、設定方法から・・・
■ FreeBSDで、消費電力を減らすための設定
/boot/loader.confに、以下の1行を追加します。
cpufreq_load="YES"
/etc/rc.confに、以下の1行を追加します。
powerd_enable="YES"
そして再起動するか、もしくは、以下のようにコマンドを実行して、即座に試してみることも可能のようです。
# kldload cpufreq
# powerd
■ ちょっと待ったぁ!
やるまえに、大切な注意事項のお知らせから。
運が悪いと、OSごとフリーズします・・・
私の場合、数台のデスクトップPCで試してみて、2台でフリーズしました。
だから、デフォルトではこの機能が有効になっていないのかもしれません。
ハングしてもいいマシンで、ハングしても大丈夫な状態にして(たとえば大容量のファイルシステムはumountしておくか、read only mountにしておく)、試しましょう・・・えぇ、私は大失敗しましたから・・・
● その動かなかった例とは・・・
- 1台は、Xeonが2個のってて、かつHyperThreadingが有効になっているマシン。HyperThreadingを無効にしたら、フリーズしなくなりました
- もう1台は、Pentium4が2個のってて、HyperThreadingは無効になっていたマシン。当初、大丈夫そうに見えて、しばらくしたら、急にフリーズしました
SMPになっていると、なんか問題があるんでしょうかねぇ?
● 動いた例
- Athlon64な自作マシン。クロック周波数も変化しますし、電圧も変化していました。
- PentiumM 1000MHz(いわゆるBanias)なノートパソコン。クロック周波数が変化することは確認できましたが、電圧の変化は確認できませんでした(たぶん変化してるんじゃないかな)。
- Pentium4 3GHzなデスクトップパソコン。周波数は変化しましたが、電圧は変化しませんでした。もともと電圧を変化させる機能が無いものかも?
- Xeon 3.6GHzが2個のったPCワークステーション(前述のやつで、HyperThreadingは無効にしている)。周波数は変化しましたが、電圧は変化しませんでした。電圧を変化させる機能があるっぽいのですが、FreeBSDのデバイスドライバが対応していない?
■ ちょっと詳しい話
cpufreqというデバイスドライバが、CPUの処理性能を変化させるインターフェイスになっていて、その裏には、AMDのPowerNow!やCool'n'Quietとか、IntelのEnhanced SpeedStepとかのドライバが実働部隊として控えていて、実際に、クロック周波数や電源電圧を変化させる仕事をしているようです。
powerdというデーモンが、OSの負荷状況に応じて、CPUの処理性能を上下させたりしています。特に重いプログラムを実行していない限り、CPUのクロック周波数が、どんどん下がっていきます。プログラムを実行すると、即座に、元のフルパワーで動き出します。
現在のCPUのクロック周波数は、次のようなコマンドでわかります。
% sysctl -a dev.cpu.0.freq
dev.cpu.0.freq: 1000
この場合、1000となっているので、たぶん、1000MHzのことなんでしょう。
ところで、よくわかってないのですが、CPUが2個あっても、dev.cpu.1.freqってのはでてきません。もしも、CPUが2個とも、同じクロック周波数で動いているとすれば、まあ、1個だけでいいわけですが・・・いまどきのでも、まだ、個別に変えられないんでしたっけ?
さてさて、なにか重いプログラムを実行させておいてから、もう一度見ると
% sysctl -a dev.cpu.0.freq
dev.cpu.0.freq: 2400
ちゃんと、フルパワーで処理しています。
ところで、消費電力は、クロック周波数に比例し、電源電圧の2乗に比例します。たとえば、クロック周波数が2.4GHzから1GHzへ落ちて、電圧が1.25Vから1.10Vへ落ちたとすると、
(1000/2400)*(1.1/1.25)^2
.32266666666666666666
ってことで、消費電力は、元の32%にまで、削減されます。もっとも、実際には、回路構成とか(clock gatingとか)いろいろな要因で、理論計算式からは誤差が生じますし、パソコンの中で、電力を消費しているのは、CPUだけでなく、ほかにもいろいろあります(ビデオチップとか、チップセットとか、ハードディスクとか、あとロスしている電力とか・・・)。あと、単位の、電力と電力量を間違わないようにね・・・中学校の理科でならうんだっけ?高校?
以下は、MBMONというツールと(/usr/ports/sysutils/mbmonにあります)、rrdtoolというツール(同じく/usr/ports/net/rrdtool)を組み合わせて、CPUなどの温度や、ファンの回転数などを記録しておき、グラフにしたものです。
- 横幅いっぱいで、1日分です。
- クロック周波数は、計測してませんでした。
- 上に上がっている部分が、CPUがフルパワーで回っているときです。
温度
CPUの電源電圧
ファンの回転数
● その他
# sysctl debug.cpufreq.verbose=1
とやると、CPUのクロック周波数が変化している様子が、ログにでてきます。
Jun 27 11:27:20 athlon64 kernel: cpufreq: get returning known freq 2400
Jun 27 11:27:20 athlon64 kernel: cpufreq: get returning known freq 2400
Jun 27 11:27:20 athlon64 kernel: cpufreq: adding abs setting 2400 at head
Jun 27 11:27:20 athlon64 kernel: cpufreq: adding abs setting 2200 after 2400
Jun 27 11:27:20 athlon64 kernel: cpufreq: adding abs setting 2000 after 2200
Jun 27 11:27:20 athlon64 kernel: cpufreq: adding abs setting 1800 after 2000
Jun 27 11:27:20 athlon64 kernel: cpufreq: adding abs setting 1000 after 1800
かなり大量にでてくるので、1度見て満足したら、さっさと止めましょう。
# sysctl debug.cpufreq.verbose=0
■ いろいろ試した例
● Athlon64なマシン
FreeBSD 5.5-STABLE #1: Wed Jun 7 17:40:23 JST 2006
root@ほげ:/usr/src/sys/i386/compile/ほげ
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: AMD Athlon(tm) 64 Processor 3400+ (2403.09-MHz 686-class CPU)
Origin = "AuthenticAMD" Id = 0xfc0 Stepping = 0
Features=0x78bfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,MMX,FXSR,SSE,SSE2>
AMD Features=0xe0500000<NX,AMIE,LM,DSP,3DNow!>
real memory = 3220373504 (3071 MB)
avail memory = 3150012416 (3004 MB)
(省略)
powernow0: <Cool`n'Quiet K8> on cpu0
となってて、sysctlでみると、こんなかんじ。
ほげ# sysctl -a | grep cpu
kern.threads.virtual_cpu: 1
kern.ccpu: 1948
cpu0: <ACPI CPU> on acpi0
powernow0: <Cool`n'Quiet K8> on cpu0
kern.smp.maxcpus: 1
kern.smp.cpus: 1
debug.cpufreq.lowest: 0
debug.cpufreq.verbose: 0
hw.ncpu: 1
hw.acpi.cpu.cx_supported: C1/0
hw.acpi.cpu.cx_lowest: C1
hw.acpi.cpu.cx_usage: 100.00%
machdep.cpu_idle_hlt: 1
dev.cpu.0.%desc: ACPI CPU
dev.cpu.0.%driver: cpu
dev.cpu.0.%location: handle=\_PR_.CPU1
dev.cpu.0.%pnpinfo: _HID=none _UID=0
dev.cpu.0.%parent: acpi0
dev.cpu.0.freq: 1000
dev.cpu.0.freq_levels: 2400/89000 2200/72000 2000/53000 1800/39000 1000/22000
dev.acpi_perf.0.%parent: cpu0
dev.powernow.0.%parent: cpu0
dev.cpufreq.0.%driver: cpufreq
dev.cpufreq.0.%parent: cpu0
● Xeonが2個なマシン
FreeBSD 6.1-STABLE #7: Tue Jun 13 15:57:03 JST 2006
root@ほげ2:/usr/src/sys/i386/compile/ほげ2
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: Intel(R) Xeon(TM) CPU 3.60GHz (3600.16-MHz 686-class CPU)
Origin = "GenuineIntel" Id = 0xf41 Stepping = 1
Features=0xbfebfbff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE>
Features2=0x659d<SSE3,RSVD2,MON,DS_CPL,EST,TM2,CNTX-ID,CX16,<b14>>
AMD Features=0x20100000<NX,LM>
Logical CPUs per core: 2
real memory = 3488481280 (3326 MB)
avail memory = 3409637376 (3251 MB)
ACPI APIC Table: <ふがふが>
FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs
cpu0 (BSP): APIC ID: 0
cpu1 (AP): APIC ID: 6
(略)
cpu0: <ACPI CPU> on acpi0
est0: <Enhanced SpeedStep Frequency Control> on cpu0
est: CPU supports Enhanced Speedstep, but is not recognized.
est: cpu_vendor GenuineIntel, msr 122d0000122d
device_attach: est0 attach returned 6
p4tcc0: <CPU Frequency Thermal Control> on cpu0
cpu1: <ACPI CPU> on acpi0
est1: <Enhanced SpeedStep Frequency Control> on cpu1
est: CPU supports Enhanced Speedstep, but is not recognized.
est: cpu_vendor GenuineIntel, msr 122d0000122d
device_attach: est1 attach returned 6
p4tcc1: <CPU Frequency Thermal Control> on cpu1
どうやら、Enhanced SpeedStepが使えていないようです。ソースファイルは
/usr/src/sys/i386/cpufreq/est.c
が該当するようなので、暇があれば、いろいろ調べたり試したりしてみましょうかね。
% sysctl dev.cpu
dev.cpu.0.%desc: ACPI CPU
dev.cpu.0.%driver: cpu
dev.cpu.0.%location: handle=\_PR_.CPU0
dev.cpu.0.%pnpinfo: _HID=none _UID=0
dev.cpu.0.%parent: acpi0
dev.cpu.0.freq: 451
dev.cpu.0.freq_levels: 3614/-1 3162/-1 2710/-1 2258/-1 1807/-1 1355/-1 903/-1 451/-1
dev.cpu.1.%desc: ACPI CPU
dev.cpu.1.%driver: cpu
dev.cpu.1.%location: handle=\_PR_.CPU1
dev.cpu.1.%pnpinfo: _HID=none _UID=0
dev.cpu.1.%parent: acpi0
● PentiumMなノートパソコン
OSは、上記とおなじときの、6.1-STABLE。
CPU: Intel(R) Pentium(R) M processor 1000MHz (999.97-MHz 686-class CPU)
Origin = "GenuineIntel" Id = 0x695 Stepping = 5
Features=0xa7e9f9bf<FPU,VME,DE,PSE,TSC,MSR,MCE,CX8,SEP,MTRR,PGE,MCA,CMOV,PAT,CLFLUSH,DTS,ACPI,MMX,FXSR,SSE,SSE2,TM,PBE>
Features2=0x180<EST,TM2>
(略)
cpu0: <ACPI CPU> on acpi0
est0: <Enhanced SpeedStep Frequency Control> on cpu0
p4tcc0: <CPU Frequency Thermal Control> on cpu0
となっていて、sysctlで見ると、こんなかんじ。
% sysctl dev.cpu
dev.cpu.0.%desc: ACPI CPU
dev.cpu.0.%driver: cpu
dev.cpu.0.%location: handle=\_PR_.CPU0
dev.cpu.0.%pnpinfo: _HID=none _UID=0
dev.cpu.0.%parent: acpi0
dev.cpu.0.freq: 75
dev.cpu.0.freq_levels: 1000/-1 900/-1 800/-1 700/-1 600/-1 525/-1 450/-1 375/-1 300/-1 225/-1 150/-1 75/-1
% sysctl dev.est
dev.est.0.%desc: Enhanced SpeedStep Frequency Control
dev.est.0.%driver: est
dev.est.0.%parent: cpu0
dev.est.0.freq_settings: 1000/-1 900/-1 800/-1 600/-1
% sysctl dev.p4tcc
dev.p4tcc.0.%desc: CPU Frequency Thermal Control
dev.p4tcc.0.%driver: p4tcc
dev.p4tcc.0.%parent: cpu0
dev.p4tcc.0.freq_settings: 10000/-1 8750/-1 7500/-1 6250/-1 5000/-1 3750/-1 2500/-1 1250/-1
残念ながら、
% mbmon -d
ioctl(smb0:open): No such file or directory
SMBus[Intel8XX(ICH/ICH2/ICH3/ICH4/ICH5/ICH6)] found, but No HWM available on it!!
No Hardware Monitor found!!
InitMBInfo: Bad file descriptor
となってしまって、mbmonで、CPUの電圧を知ることはできませんでした。
portupgradeとかで負荷をかけたり、いろいろ使ってみて、体感としては、この機能を有効にする前よりは、ファンが高速回転する時間が少なくなったような気がします。気のせいかも。
■ ほかのOSはどうなの?
Windows用のユーティリティは、ちょこっとさがせば、すぐ見つかるでしょう・・・
とりあえず、Linuxな、Fedora Core 5の場合を、ちょっとだけ調べてみました。
マシンは、ラックマウントな1Uサーバで、CPUは、Opteron 250が2個。
実は、最新のBIOSへアップデートしたら、PowerNow!が使えるようになりました。アップデート前は、ACPIまわりがおかしかったっぽいです。
ブート時のログに、こんな風に表示されます。
powernow-k8: Found 2 AMD Athlon 64 / Opteron processors (version 1.60.0)
powernow-k8: 0 : fid 0x10 (2400 MHz), vid 0x2 (1500 mV)
powernow-k8: 1 : fid 0xe (2200 MHz), vid 0x6 (1400 mV)
powernow-k8: 2 : fid 0xc (2000 MHz), vid 0xa (1300 mV)
powernow-k8: 3 : fid 0xa (1800 MHz), vid 0xc (1250 mV)
powernow-k8: 4 : fid 0x2 (1000 MHz), vid 0xe (1200 mV)
cpu_init done, current fid 0x10, vid 0x2
powernow-k8: 0 : fid 0x10 (2400 MHz), vid 0x2 (1500 mV)
powernow-k8: 1 : fid 0xe (2200 MHz), vid 0x6 (1400 mV)
powernow-k8: 2 : fid 0xc (2000 MHz), vid 0xa (1300 mV)
powernow-k8: 3 : fid 0xa (1800 MHz), vid 0xc (1250 mV)
powernow-k8: 4 : fid 0x2 (1000 MHz), vid 0xe (1200 mV)
cpu_init done, current fid 0x10, vid 0x2
そして、普通にFedora Core 5をインストール(Core 3からアップグレード)しただけなんですが、勝手にcpuspeedというのがインストールされて、勝手に動いていて、知らないうちに、よきにはからって、CPUの周波数と電圧をコントロールしてくれていました(xmbmonで、その様子を確認)。
Linuxでは、「/sys/devices/system/cpu/cpu0/cpufreq/」とか「/sys/devices/system/cpu/cpu1/cpufreq/」以下で、CPUのパフォーマンスをコントロールできるようになっているようです。
% ls /sys/devices/system/cpu/cpu1/cpufreq/
/sys/devices/system/cpu/cpu1/cpufreq:
affected_cpus scaling_cur_freq
cpuinfo_cur_freq scaling_driver
cpuinfo_max_freq scaling_governor
cpuinfo_min_freq scaling_max_freq
scaling_available_frequencies scaling_min_freq
scaling_available_governors scaling_setspeed
こんなふうにして、CPUのクロック周波数を確認できます。
(現在の周波数)
# cat /sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_cur_freq
1000000
(設定可能な最高周波数)
# cat /sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_max_freq
2400000
(設定可能な最低周波数)
# cat /sys/devices/system/cpu/cpu1/cpufreq/cpuinfo_min_freq
1000000
ちなみに、「/proc/cpuinfo」でも、今の周波数が見えました。
# cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 15
model : 5
model name : AMD Opteron(tm) Processor 250
stepping : 10
cpu MHz : 1000.000
cache size : 1024 KB
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext lm 3dnowext 3dnow
bogomips : 2004.69
TLB size : 1024 4K pages
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp
processor : 1
vendor_id : AuthenticAMD
cpu family : 15
model : 5
model name : AMD Opteron(tm) Processor 250
stepping : 10
cpu MHz : 1000.000
cache size : 1024 KB
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext lm 3dnowext 3dnow
bogomips : 2004.69
TLB size : 1024 4K pages
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp