コード探偵 ファイル03「タイムルーラーで現場測定」
タイムルーラーを使ってゲームの更新部分と描画部分に掛かった時間は以下のコードで測定することができます。
/// <summary>
/// ゲームの更新(衝突判定、入力処理、オーディオの再生など)
/// </summary>
/// <param name="gameTime">タイミング値のスナップショット</param>
protected override void Update( GameTime gameTime )
{
// タイムルーラーにフレーム開始を伝える
timerRuler.StartFrame();
// 更新期間、"Update"の測定開始
timerRuler.BeginMark( "Update", Color.Blue );
// 他の処理...
// 他のコンポーネントを更新
base.Update( gameTime );
// 更新期間、"Update"の測定終了
timerRuler.EndMark( "Update" );
}
/// <summary>
/// ゲームの描画
/// </summary>
/// <param name="gameTime">タイミング値のスナップショット</param>
protected override void Draw( GameTime gameTime )
{
// 描画期間、"Draw"の測定開始
timerRuler.BeginMark( "Draw", Color.Yellow );
// 他の処理...
// 他のコンポーネントを描画
base.Draw( gameTime );
// 描画期間、"Draw"の測定終了
timerRuler.EndMark( "Draw" );
}
また、以前の投稿で述べたようにCPUがGPUを待っている時間を測定することができます。PresentはGame.EndDraw内で呼ばれるので、EndDrawメソッドをオーバーライドして、タイムルーラーでマークすることでPresentに掛かった時間を測定することができます。
/// <summary>
/// EndDrawをオーバーライドする
/// </summary>
protected override void EndDraw()
{
// EndDrawの中でPresentが呼ばれるのでbase.EndDrawメソッドを
// マークすることでPresentを呼び出すのに掛かった時間を測定できる
timerRuler.BeginMark("Present", Color.Red);
base.EndDraw();
timerRuler.EndMark("Present");
}
これで、タイムルーラーを使って以下の時間を測定することができ、この情報を元にしてCPUバウンドかGPUバウンドなのかを知ることができます。
- 更新に掛かった時間
- 描画に掛かった時間
- Present呼び出しに掛かった時間
1の更新に掛かった時間が多すぎる場合、特にこれだけで16.6msを超えているようであれば、CPUバウンドということになります。
2の描画に時間が掛かりすぎている場合、描画中にGPUをブロックするようなコード(SetData、GetDataメソッド)がない限りは、これもCPUバウンドということになります。
3のPresentに時間が掛かった場合は、CPUがGPUを待っている状態なのでGPUバウンドということになります。
最後に1と2に掛かった時間が16.6msより少なく、3に殆ど時間が掛かってない場合は、CPUバウンドか、CPUとGPUがバランスの取れている状態の二つの可能性があります。この二つの可能性から絞り込むには前回と同じ手法を使います。
ロードバランスの変更
タイムルーラーはリアルタイムに処理時間を測定するので、判りやすいように動画にしてみました。
この動画では、GPUバウンドからバランスの取れた状態へ変更する様子と、描画方法を変更することによって、CPUとGPUのロードバランスが変わるという例を紹介しています。
具体的にはマテリアルバッチを用いた複数のキャラクターの描画からHWインスタンスを使った手法に変更することによって、CPUの処理速度が三倍になった変わりにCPUがGPUを待っている時間が倍になるというロードバランスがCPUからGPUへと変化したのが判ると思います。
ただし、CPUの待ち時間が倍になっただけで、GPUの処理量が二倍になった訳ではないということに注意する必要があります。GPUの処理量がどれだけ増えたかを推測するには、変更前のCPU待ち時間が14ミリ秒まで掛かっているに対して、変更後は15ミリ秒付近で終わっているのでGPUの処理量は1ミリ秒程増えたということになります。
これで処理落ちしている原因がCPUバウンドなのかGPUバウンドなのかが判りました。
つづく……。