CPU使用率100%対策を考える
ゲームをプレイしていて演出中にCPUの使用率が一時的に100%になるというのならば納得できるものの、常時CPUの使用率が100%というのはいただけません。OS全体が重くなってほかのアプリケーションの使い勝手が悪化するし、CPUがフル稼働しているということは発熱や消費電力が増大してしまいます。環境問題が注目されている中で無駄に消費電力を増やしているのは好ましくないといえるでしょう。すべての面で完全な解決というのは難しいものの、対応策を知っておいても損はないはずです。
発生原因の推測と擬似的な再現ツール
WindowsのAPIでGetMessage関数あたりをwhileループで待つようにプログラムすればおそらく常時CPUの使用率が100%となることがないと思われます。試したのが結構前のことなので記憶に自信がありませんが、MSDNの推奨しているコードで大丈夫だったような気がするので……。もし、記憶が間違っていたら申し訳ない。
何も演出がなく、ただキー入力やマウス入力を待っている状態でCPU使用率100%となる問題が起こっているのは、おそらくマルチタスクを考慮する必要がなかったMS-DOS時代からプログラムの書き方を変えていないプログラマーがいるからだと思われます。入力待ちで何もすることがない状態で、入力待ちをするループ処理部分でCPUパワーを全部使って秒間何百回とかに対応できるような無駄に過剰な待ち受け状態となっているというわけですね。プレイヤーはそのような速度で入力をしない……というかできません(笑)。
まあ、文字だけでの説明ではわかりにくいため、「百聞は一見にしかず」ということで、わかりやすいようにそのようなマルチタスクを考慮しない作りのプログラムが実行されている状態を再現してみる簡単なプログラムを作成してみました。☠SleepTest.zipをダウンロードしてLhaplusやLhasaなどのツールで解凍してみてください。srcフォルダ内のファイルはDelphi7で記述したツールのソースコードです。プログラムに興味のある人ならばともかく、そうでない人はそのフォルダ内のファイルを気にしなくて構いません。プログラムのコードは非常にシンプルで、アプリケーションがアイドル状態(ゲームにおける入力待ちに近い状態)で呼ばれるOnIdleイベントにLoopExecuteを割り当て、本来はバックグラウンドで処理して終わったら処理終了を示すDoneをTrueにするところをFalseで返して延々とLoopExecuteを実行させて擬似的に待ち受け状態を再現しているだけです。
テストツールを起動する前に、Ctrl+Shift+Escを押すか、Ctrl+Alt+Deleteを押すか、タスクバー上で右クリックしてタスクマネージャを起動しましょう。そしてパフォーマンスのタブをクリックしてCPU使用率を見られるようにしてください。その後、SleepTest.exeをダブルクリックして起動します。実行ボタンを押すと、CPU使用率はPentiumII/III/4などのシングルコアCPUならば使用率が100%になり、デュアルコアCPUのPentiumDやCore2DuoなどのCPUでは50%になるはずです。CPUを1つをまるまるフルパワーで使い潰すためにそのような使用率となります。これが待ち受け状態でCPUパワーの全力を使ってひたすら待っているという状態を示しているわけです。
ここで「ループ内でSleep(20)を実行する」にチェックを付けてみてください。SleepはWindowsのAPIに用意されているもので、指定した時間だけほかのアプリケーションにCPUを解放するというものです。APIなので開発言語を問わず使えます。指定する時間はミリ秒単位なので、テスト用のツールではSleep(20)とわずか20ミリ秒を解放しているだけです。わずか20ミリ秒だけほかのアプリケーションにCPUパワーを優先的に割り当てる設定を実行するだけなのですが……入力待ちのループ内にこのプログラムコード1行を挿入するだけでどのようにOS全体での負荷の変化があるのかを確認できることでしょう。CPUの使用率が激減してツールを実行していないのとほとんど変わらないCPU使用率になるはずです。これは中断ボタンを押して比較してみるとわかります。
該当部分のコード → if (UseSleep.Checked) then Sleep(20);
要するにチェックがついていたら、WindowsAPIのSleep(20)を実行を追加してはさんでいるだけです。わずか20ミリ秒をほかのアプリケーション向けにCPUを解放するだけでここまで軽くなるということをご確認できたでしょうか? こんな単純な「Sleep(20)」を1行追加するだけで大きな差がつくことでわかるように、プログラマーがマルチタスクを考慮しているかしていないかでプレイヤーが大きな影響を受ける可能性があるのです。プログラム中で実行頻度の高くなる部分に入れておけばほかのアプリケーションとの並列動作が快適になるわけですね。
とはいっても、これはCPUの使用率が常時100%になってしまうプログラムの例と解決方法の1つとして紹介したものであり、高負荷になるアプリケーションのすべてがこのような作りとなっているわけではないことに留意してください。CPU使用率100%となるプログラムの中には、わずか1行で解消できるものもあるという現実を皆さんに知ってもらうためのサンプルですので。マルチタスクを考慮していないプログラムが少しでも減るようにという願いを込めてこの記事を執筆しているともいえるかもしれませんね。
なお、ツールの優先度設定のほうはオマケで用意してみたもので、OS上でツールが実行される優先度を変更するためのものです。「ループ内でSleep(20)を実行する」にチェックを付けない状態でのテストを想定してます。PCの環境によっては実感できないだろうと思いますが、リアルタイムにすればほかのアプリケーションが使いにくくなるほど重くなるとか、通常では重いけど低にするとほかのアプリケーションも普通に動かせるとか、そのあたりをテストできるようにしてみたつもり……。あくまでもオマケなのでこちらのテスト機能はあまりアテにしないでほしいかな。
優先度の変更で回避する
常時CPUの使用率が100%になるアプリケーションは、タスクマネージャでプロセスのタブを見て負荷の高いものを右クリックし、「優先度の設定」を「低」もしくは「通常以下」に変更するとよいでしょう。これにより、ほかのアプリケーションのほうがOSから見て相対的に優先度が高くなるため、たいていは普通の速度で動くようになります。
とはいえ、毎回起動するたびに優先度の変更を行なうのはかなりの手間です。インストールしたアプリケーションがデスクトップやスタートメニューにショートカットを作成しているのであれば、それを右クリックして設定を変更するとよいでしょう。ショートカットのタブにリンク先というのがあるので、その先頭部分に「cmd /c start /low 」を追加します。これで優先度が低で起動できるようになります。CPUの使用率は100%のままですが、ほかのアプリケーションへの影響はほとんどなくなるのでだいぶ楽になるはずです。
ツールで解消
無料で公開されている実行優先度自動設定プログラム「オートギア」というフリーソフトウェアを使うとCPU使用率100%ゲームへの対策が楽になります。「オートギア」を起動して「追加」を押して「参照」でゲームをインストールしたフォルダにあるゲームの実行ファイルを指定するか、ゲームを起動してから「一覧」で起動中のアプリケーション一覧から優先度を変更したいプログラムを選択。指定優先度を「低」もしくは「通常以下」にしましょう。そして「セーブ」を押して設定を保存。 このままでは毎回「オートギア」を起動した際に「ロード」しないといけないため、あまりにも使いにくいと思います。そこで、「オプション」にある「ファイル」で「オートセーブ」「オートロード」にチェックを付けて「OK」を押して設定を完了させましょう。これで自動的に保存と呼び出しが行なわれるようになります。「オプション」の「一般」にある「スタートアップにショートカットを作成します。」にチェックを付けておくとWindows起動時に「オートギア」が自動起動するようになってよいかも。そうすることで、優先度を変更したいアプリケーションが起動されるとそれを検出し、自動的に指定しておいた優先度へ変更してくれるようになります。Windows起動時の自動起動と組み合わせれば、お手軽に本来は重くてほかのアプリケーションと共存できないようなものも普通に使えるようになるわけです。
逆に使いたいアプリケーションの優先度を高くする設定を行なうという方法もあります。動画再生でのコマ落ちを避けるためにプレーヤー関係の優先度を高くするというのも「オートギア」の活用方法の一例といえるでしょう。
以下に本件に関連する役立ちそうなツールを列挙しておきます。今回紹介した方法ではしっくりと来なかった人はこれらのツールも試してみてはいかがでしょうか?
2007-12-06 (by 天城螢)