last update: 2013/09/03

2003/04/10

ファンレスへの道

こっちに帰ってきてとりあえずMURAMASAを友人たちに披露してみたところ、「薄い」「軽い」「折れそう」などのいろんな評価をもらいました(実際、折りそうです)。

で、なにげなくビデオパフォーマンスも前のマシン(SiS630)よりいいんだぞ、という所を見せようとDirectXのゲームを動かしてみたんですよ。……あー、やっぱむかしよりスカスカ動いてるよねー、なんて思いつつ、異変に気がつきました。

あれー、CPU使用率が100%なのにファンが回らないなぁー

DirectX(っていうかDirect3D)はその仕様上どうやってもCPU使用率が100%になっちゃうわけで、そうなると発熱が酷いことになってMURAMASAでもブンブンファンが回ります(ちなみに、ファンの強さは2,3段階あるっぽいです)。しかしながら、この時ばかりは回らなかったんですよ。……これ、回るはずのファンが回らないと放置したら熱がたまってCPUが炭になるんじゃないか?

と思ったら、よーくみたら電源コードが抜けてるんですよね。いやぁ、毎度オレってお馬鹿だなぁ、なーんて思いつつ電源を差して電源を切り替えるとさっそくファンが回り始めました。ふむ。

ってか、なんでバッテリ駆動でファンが回らなかったか調べてみると、なにげなく電源スキームがプレゼンテーションになってたので(最近はずっとこれです)Degradeでの稼働。つまり、最高クロックは566MHzだったからCPUが100%でも大した発熱じゃなくて、ファンが回らなかったと。はい、おしまい。

って、これって意外と重要なんじゃ?

566MHz(昔風にいうとバッテリオプティマイズモード)でCPU使用率100%でもファンが回らないって事は、これ、ACつなぎつつDegradeで動かしても最高クロックが566MHzになるからファンが回らないって事で(まぁ、HDDが発熱すれば回っちゃうでしょうがCPUが原因で回ることはないと)、ファンレスPC気分で使えるじゃないですか。

ファンレス、響きがいいですよねー。モバイルの夢ですよねー。

ちうわけで、今日は常に最高566MHzで動かすための電源スキームを作ってやろうというお話です。

今日の電源スキーム

というわけで、AC電源でもDegradeで動かたいー、という欲求をかなえるためにいろいろレジストリ回りを調べてみましたが、それっぽいのを見つけるも結局違ったようで、Degradeに落とすようにできません。

で、こんな時はWin32APIだ、とPlatform SDKのヘルプを眺めてたら、Read/WriteProcessorPwrSchemeなんていうAPIがありました。ちなみに、これはWinXP以降でのサポートです(powrprof.dllが必要)。そのRead/WriteProcessorPwrScheme関連の定義がこちら。


BOOLEAN ReadProcessorPwrScheme(
   UINT uiID,
   PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy
);
BOOLEAN WriteProcessorPwrScheme(
   UINT ID,
   PMACHINE_PROCESSOR_POWER_POLICY pMachineProcessorPowerPolicy
);

typedef struct _MACHINE_PROCESSOR_POWER_POLICY {
   ULONG Revision;
   PROCESSOR_POWER_POLICY ProcessorPolicyAc;
   PROCESSOR_POWER_POLICY ProcessorPolicyDc;
} MACHINE_PROCESSOR_POWER_POLICY, *PMACHINE_PROCESSOR_POWER_POLICY;

typedef struct _PROCESSOR_POWER_POLICY {
   ULONG Revision;
   UCHAR DynamicThrottle;
   UCHAR Spare[3];
   ULONG Reserved;
   ULONG PolicyCount;
   PROCESSOR_POWER_POLICY_INFO Policy[3];
} PROCESSOR_POWER_POLICY, *PPROCESSOR_POWER_POLICY;

つまり、プロセッサポリシーは電源スキームごとに定義されていて、プロセッサポリシーごとにDynamicThrottleでAC駆動時とDC駆動時の動的スロットルの動作を規定できる仕様になってます。そのDynamicThrottleに入る値はこれ。

PO_THROTTLE_ADAPTIVE

Attempts to match the performance of the processor to the current demand. This policy will use both high and low voltage and frequency states. This policy will lower the performance of the processor to the lowest voltage available whenever there is insufficient demand to justify a higher voltage. This policy will engage processor clock throttling if the C3 state is not being utilized, and in response to thermal events.

PO_THROTTLE_CONSTANT

Does not allow the processor to use any high voltage performance states. This policy will not engage processor clock throttling, except in response to thermal events.

PO_THROTTLE_DEGRADE

Does not allow the processor to use any high voltage performance states. This policy will engage processor clock throttling when the battery is below a certain threshold, if the C3 state is not being utilized, or in response to thermal events.

PO_THROTTLE_NONE

No processor performance control is applied. This policy always runs the processor at its highest possible performance level. This policy will not engage processor clock throttling, except in response to thermal events.

というわけで、適当にWinXPに既にある6つの電源スキームの他に7つ目の電源スキームを作って、それをReadProcessorPwrSchemeして、ProcessorPolicyDc.DynamicThrottle=PO_THROTTLE_DEGRADEしてやれば良さそうです。

さっそくやってみると、ちゃんとAC電源駆動時もCPUがアイドルな時は300MHzぐらいまで落ちています。そして、100%の負荷をかけても566MHzでストップしているのでDegradeで動いているといっていいでしょう。

で、実はここからが本題。私は電源スキームをプレゼンテーションにして稼働させてることが多いんですが、それはプロセッサポリシーがConstant/Degradeであるという情報を元にしているわけです。しかしながら、Constantの動作モードの説明を見る限り、私のマシンでは明らかにそれとは違う動きをしてるんですよね。一応、話の上ではConstantはCPUクロックが「バッテリオプティマイズモード固定」で動くことになっています。つまり、私もマシンではCPU負荷がどんな状態であろうと常に566MHzをキープすることになっているはずです。が、実際には1GHzと566MHzを負荷によって切り替えるというAdaptiveのモードとして振る舞うわけです。

はたして、WindowsXPではConstantはAdaptiveと同義として扱われてしまっているのか、それとも単にプレゼンテーションの電源スキームのプロセッサポリシーがAdaptive/Degradeに変わってしまったのか。これを検証するべくReadProcessorPwrScheme(2, &mppp)してみると、……プレゼンテーションの電源スキームでもAC動作時のプロセッサポリシーがConstantではなくAdaptiveになってました。ためしにWriteProcessorPwrSchemeでAC動作時のプロセッサポリシーをConstantに変えてみると、ちゃんと566MHz固定で動作しました。つまり、デフォルトのWindowsXPにおいてConstantを使う電源スキームはない、ということなんですかね。

どうでもいいけど長い注釈: Read/WriteProcessorPwrSchemeの第1引数は電源スキームのIDであるわけですが、そのスキーマIDと各スキーマの対応はEnumPwrSchemesを使って得ることができます。まぁ、自分のマシンだけでしか使わないアプリケーションであれば、レジストリエントリのHKEY_CURRENT_USER\Control Panel\PowerCfg\PowerPoliciesの下にスキーマIDをキー名として各電源スキームが保存されているので、ここから直接スキーマIDを調べてハードコーディングしちゃうというのも手です。ってか、私は面倒なのでハードコーディングでやっちゃったです。

ともあれ、こうしてDegrade/DegradeやConstant/Degradeな電源スキームを作ってみたわけですが、AC動作時までわざわざDegradeでリニアに動作クロックを落として動かさなくても、とりあえずConstantで動かしておけばCPU100%でファンが回り出してうるせーよ、という現象に悩まされることはなくなったかなー、と。

ちなみに、このアプローチはCentrinoなVAIO U(ファンレス)の最低クロックでしか動作しないCeleronと同じなんですよね。この「WinXPでConstantな電源スキームが存在しない」というのはバグなのか仕様なのか知りませんが、CPUの動作ポリシーは現在GUIで変える手段がないので面倒ったらありゃしないです(それとも、プレゼンテーションがConstantになってなかったのって私だけ、とかいうオチか?)。で、GUIで変える手段がないという事は、CUIならあるのか、というと実はあるんです。

一応、Windows Server 2003のツールということになっているんですが、KnowledgeBaseの方を参照するとわかるとおり、Windows XP SP1のOEM版のOEM PreInstall Kitに入ってるらしいです。って、んなもん入手できるかっ。このMURAMASAにもWinXPSP1のOEM版が入ってるわけですが、I386をはじめとするWinXPのインストール用ファイル群の中にそれっぽいのは見つかりませんでした。そういえば、3月の自作した友人がWinXPSP1のOEM版(しかもPlus!つき)を買ってたのでそのCDの中に入ってるかどうか気が向いたら調べてこようと思います。

ちうわけで、WindowsXPのプロセッサポリシーのあれこれをお届けしました。

あ、開発環境のある人ならこの手の実力行使も可能なわけですが、一般ユーザーにはこういう(直接Win32APIを叩かないとできないような)芸当はできないわけで、やっぱりPowercfg.exeの入手もそう易々とはできないことを勘案するとプロセッサポリシーの設定ができるツールを作ったりしてほしいとかいう需要はあるんですかね。

追記:566MHzで100%の負荷かけて1時間ほど放置してみましたが、やっぱりHDDも回ってる関係でファンが回り始めますね。

comments powered by Disqus