CPUバウンドとGPUバウンド
もしあなたが60FPSのゲームを作ると決めた場合、ゲーム内全ての処理を1/60秒、つまり16.66ミリ秒以内に終わらせないといけません。ゲームの規模が大きくなればなるほど、処理する内容も多くなるとともに16.66ミリ以内に処理を終えることが難しくなってきて、ついには16.66ミリ秒以内に処理を終えることのできない状態、つまり処理落ち状態になってしまいます。
XNAフレームワーク上でゲームを作っている場合、固定更新設定にしていれば処理落ちした場合は描画部分をスキップするという機能があるので、ある程度の処理落ちは軽減することができます。ですが、この方法は描画をスキップしてごまかしているだけなので、ゲームのシミュレーション部分は処理落ちしなくとも、コマ落ち状態になってしまいます。また、隠蔽できないほどの処理落ちが発生している場合は効果がありません。
この処理落ちや、コマ落ち状態を防ぐには、最適化をする必要があります。
さて、どこから最適化をするべきでしょうか?コーディングするのに苦労した複雑な部分?それともポリゴン数を沢山使っているモデルを調べる?
答えはどちらでもありません。最適化をするときに最も重要なのは、ボトルネックとなっている部分を特定することです。あてずっぽうにコードを変えたり、データを変えたりするのは、あなたが超能力者でもないかぎり時間の無駄でしかありません。
<ボトルネックを見つける重要性>
ある日、XNA向けのゲームを個人で作っている同僚のジェイスが処理落ち問題に直面していた時に私のところに相談してきたことがありました。
ジェイス「処理落ちしているんだ。原因は複雑な計算部分だと思うんだけど、良いアルゴリズム知らない?」
私「ボトルネックは特定した?」
ジェイス「きっと、複雑な計算部分だよ、それ意外に考えられない」
結局、その同僚は処理落ちの原因となっていると思われる箇所の最適化を始めました。
二日後……
ジェイス「計算部分を最適化したけど、ダメだった。なんかいい手はない?」
私「タイムルーラーを使って、ボトルネックを調べてみたら?」
ジェイス「うーん、とりあえず使ってみるよ」
30分後…
ジェイス「ボトルネック箇所を見つけた!ぜんぜん関係ないところでパフォーマンス的に手を抜いていたところが原因だった!」
これはあてずっぽうに最適化するのに二日掛けても解決しなかったのが、正しい最適化手法を使うことでボトルネックの発見、修正まで30分しか掛からなかったという好例です。
</ボトルネックを見つける重要性>
CPUバウンドとGPUバウンド
処理落ちする原因は様々ですが、大別すると以下の三つしかありません。
- CPUバウンド
- GPUバウンド
- CPU、GPUのバランスはとれているが、どらも高負荷になっている
CPUバウンドとはGPUに比べてCPUの処理量が多すぎてGPUがヒマになっている状態、つまりGPUがCPUに縛られている(バウンド)状態のことです。図にすると以下のようになっています。
この図の場合はゲームの更新部分(Update)の処理時間が掛かっているので、その間にGPUが前フレームの描画処理を終え、次のフレームの描画命令待ちになっています。
この状態で、描画するモデルの頂点数を少なくしたりする最適化を施しても、GPUが更にヒマになるだけでゲーム全体のパフォーマンスアップにはなりません。
これとは逆にGPUへの負荷が掛かり過ぎている状態をGPUバウンドと呼び、以下の図の状態になっています。
この場合によく見受けられる現象としては、Present内でGPUが前フレームの描画が終了するまでの待ちが入るので、見かけ上はCPUの処理時間が掛かっているように見えることです。こういった、CPUがGPUを待つ状態というのは動的頂点バッファへの書き込み時などにも発生することがあるので、CPUバウンドと勘違いしてしまうことがあることに注意しないといけません。
ですが、Presentの処理時間が掛かっているからといって、常にGPUバウンドであるとは限らないことです。Present内ではコマンドバッファ発行処理も含まれるので、多くの描画命令を発行している場合にもPresentの処理時間が掛かることもあるということです。
最後に3のケースですが、この状態になること自体が少ないうえに、仮にこの状態になった場合、更に二つのケースに分類されます。現状の方法が使っているプラットフォームに合わない方法で負荷が掛かりすぎているか、単にプラットフォームの性能限界に達しているかのいずれかです。前者の場合は、プラットフォームに合った方法に最適化することもできますが、後者の場合はコード的な最適化は限界に達しているので、ゲーム中のオブジェクト数などを少なくしたり、モデルデータを小さくするなどをします。
この三つのケース、特に処理落ちの原因がCPUバウンドかGPUバウンドであるかを判別することが最適化の最初の一歩とになります。
次回に続く……
Comments
Anonymous
July 29, 2014
Exam Ref 70-483 の学習をしていて「CPU-bound」という用語が出てきたため、検索してこちらにたどり着きました。 「CPUバウンドとはGPUに比べてCPUの処理量が多すぎてGPUがヒマになっている状態、つまりGPUがCPUに縛られている(バウンド)状態のことです」と記述されています。 その後MSDN の別の文章を確認したところ、CPUバウンドはCPUが忙しいままの使用状態であるとのことでした。 上記ほど複雑な状態ではないのではないかと考えて投稿いたしました。 よろしくお願いいたします。 Multithreading Performance(January 31, 1996) msdn.microsoft.com/.../ms810437.aspx " A CPU-bound computation is a computation that spends most of its time keeping the CPU busy. "Anonymous
August 08, 2014
おっしゃる通り、CPU/GPUバウンドの定義自体は簡潔に済ますことができますが、実際にはそのどちらかを見極めて最適化する必要があるので、この記事ではそうなったときにXNAで作られたゲームがどのような振る舞いをするのかを説明し、後に続く記事でその判別方法を紹介するというシリーズになっています