2006年6月29日木曜日

(FreeBSD)そのパソコン、無意味に熱くなってませんか? ――― CPUの消費電力を減らす方法

ここ数日、急に、暑くなってきました。



あぁ、暑い、あつい、熱い、といえば、パソコンも暑くなる原因の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がフルパワーで回っているときです。


温度



20060628mbmontemp







CPUの電源電圧



20060628mbmonvc





ファンの回転数



20060628mbmonfan





● その他

# 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



0 件のコメント:

コメントを投稿