ここでは、Windows Performance Toolkit の一部として付属する XPerf ツールと GPUView ツールを使用して、DirectX アプリの最も重要なパフォーマンス時間の測定値を測定する方法を示します。 これは、ツールを理解するための包括的なガイドではなく、DirectX アプリのパフォーマンスを分析するための具体的な適用性です。 ここで説明する手法のほとんどはすべての DirectX アプリに関連していますが、スワップ チェーンを使用するアプリに最も関連しており、SIS/VSIS と XAML アニメーションを使用する XAML 上に構築された DirectX アプリケーションには関係ありません。 主要なパフォーマンス時間の測定、ツールを取得してインストールする方法、パフォーマンス測定トレースを取得し、それらを分析してアプリのボトルネックを理解する方法について説明します。
ツールについて
XPerf
XPerf は、詳細なシステムとアプリのパフォーマンスとリソースの使用状況を測定および分析するために設計された、Windows イベント トレーシング (ETW) の上に構築されたパフォーマンス分析ツールのセットです。 Windows 8 以降、このコマンド ライン ツールにはグラフィカル ユーザー インターフェイスがあり、Windows Performance Recorder (WPR) と Windows Performance Analyzer (WPA) と呼ばれます。 これらのツールの詳細については、 Windows Performance Toolkit (WPT): Windows Performance Toolkit の Web ページを参照してください。
ETW は、要求されたカーネル イベントを収集し、イベント トレース ログ (ETL) ファイルと呼ばれるファイルに保存します。 これらのカーネル イベントは、アプリの実行時にアプリとシステムの特性に関する広範な情報を提供します。 データを収集するには、トレース キャプチャを有効にし、分析が必要な目的のアプリ シナリオを実行し、ETL ファイルにデータを保存するキャプチャを停止します。 その後、コマンド ライン ツールxperf.exeまたはビジュアル トレース分析ツール xperfview.exe を使用して、同じコンピューターまたは別のコンピューターでファイルを分析できます。
GPUView
GPUView は、グラフィックス処理装置 (GPU) と CPU のパフォーマンスを決定するための開発ツールです。 これは、ダイレクト メモリ アクセス (DMA) バッファー処理と、ビデオ ハードウェア上の他のすべてのビデオ処理に関するパフォーマンスを確認します。
GPU に大きく依存する DirectX アプリの場合、 GPUView は、CPU と GPU で行われる作業の関係を理解するための強力なツールです。 GPUViewの詳細については、「GPUView の使用」を参照してください。
XPerf と同様に、ETW トレースは、最初にトレース サービスを開始し、検討中のアプリの分析が必要なシナリオを実行し、サービスを停止して ETL ファイルに情報を保存することによって取得されます。 GPUView は、ETL ファイルに存在するデータをグラフィカル形式で表示します。
GPUView ツールをインストールした後は、[GPUViewヘルプ] メニューの [GPUView のメイン ディスプレイ] トピックを読み取うことをお勧めします。 これには、GPUView UI の解釈方法に関する有用な情報が含まれています。
ツールのインストール
XPerf と GPUView の両方が Windows パフォーマンス ツールキット (WPT) に含まれています。
XPerf は、Windows 用 Windows ソフトウェア開発キット (SDK) の一部として出荷されます。 Windows SDKをダウンロードします。
GPUView は、Windows Assessment and Deployment Kit (Windows ADK) で使用できます。 Windows ADK をダウンロードします。
インストール後、 XPerf と GPUView を含むディレクトリをシステムの "Path" 変数に追加する必要があります。
[スタート] ボタンをクリックし、「システム変数」と入力します。 [システムのプロパティ] ウィンドウが開きます。 [システム環境変数の編集] をクリックします。 [システムのプロパティ] ダイアログ ボックスから [環境変数] を選択します。 "Path" 変数は、"システム変数" にあります。 xperf.exe を含むディレクトリを追加し、パスにGPUView.exe します。 これらの実行可能ファイルは、"Windows Kits" 内の "Windows Performance Toolkit" ディレクトリにあります。 既定の場所は C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit です。
パフォーマンス時間の測定
ほとんどのアプリは、スムーズに実行され、ユーザー入力に応答することを期待しています。 ただし、必要なシナリオによっては、パフォーマンスの 1 つの側面が別の側面よりも重要になる場合があります。 たとえば、タッチ タブレット PC で実行されているニュース リーダー アプリの場合、最も重要な側面は、一度に 1 つの記事を表示し、同じ記事または別の記事をパン/ズーム/スクロールすることです。 このシナリオでは、フレームごとにすべてのコンテンツをレンダリングする機能は必要ありません。 ただし、タッチ ジェスチャで記事をスムーズにスクロールする機能は非常に重要です。
別の例では、フレームがドロップされた場合に多くのアニメーションを使用するゲームまたはビデオ レンダリング アプリがグリッチになります。 この場合、ユーザー入力を中断することなく画面にコンテンツを表示する機能が非常に重要です。
アプリのどの部分が問題であるかを理解するために、最初に最も重要なシナリオを決定します。 アプリの主要な側面を理解し、それらがどのように実行されるかを理解すると、ツールを使用して問題を探す方が簡単になります。
最も一般的なパフォーマンス時間メトリックの一部を次に示します。
起動時間
プロセスの起動から最初に画面に表示されるまでの時間を測定します。 この測定値は、システムがウォームである場合に便利です。つまり、アプリを数回起動した後に測定が行われます。
フレームあたりの CPU 時間
CPU が 1 フレームのアプリ ワークロードをアクティブに処理する時間。 アプリがスムーズに実行されている場合、1 つのフレームに必要なすべての処理は、1 つの v 同期間隔内で行われます。 モニターのリフレッシュ レートが 60Hz の場合、これはフレームあたり 16 ミリ秒になります。 CPU の時間/フレームが 16 ミリ秒を超える場合は、バグのないアプリ体験を実現するために CPU の最適化を検討する必要があります。
フレームあたりの GPU 時間
GPU が 1 フレームのアプリ ワークロードをアクティブに処理する時間。 フレーム分のデータの処理にかかった時間が 16 ミリ秒を超えると、アプリは GPU バインドされます。
アプリが CPU と GPU のどちらにバインドされているかを理解できると、コードの問題のある部分が狭くなります。
パフォーマンス時間測定トレースの取得
トレースを実行するには、次の手順を実行します。
- 管理者としてコマンド ウィンドウを開きます。
- アプリが既に実行されている場合は、アプリを閉じます。
- Windows Performance Toolkit フォルダー内の gpuview ディレクトリにディレクトリを変更します。
- イベント トレースを開始するには、「log.cmd」と入力します。 このオプションは、最も興味深いイベントをログに記録します。 その他の使用可能なオプションでは、イベントのさまざまなスコープがログに記録されます。 たとえば、"v" または詳細ログ モードでは、 GPUView が認識しているすべてのイベントがキャプチャされます。
- サンプルを起動し、分析する必要があるパフォーマンス パスをカバーする方法でサンプルを実行します。
- コマンド ウィンドウに戻り、「log.cmd」と再度入力してログ記録を停止します。
- これにより、 gpuview フォルダーに "merged.etl" という名前のファイルが出力されます。 このファイルを別の場所に保存し、同じコンピューターまたは別のコンピューターで分析できます。 スタック キャプチャの詳細を表示するには、アプリに関連付けられているシンボル ファイル (.pdb) を保存します。
測定
注
ジオメトリ実現サンプルの測定値は、統合された DirectX11 グラフィックス カードを備えた Quad Core マシンで取得されます。 測定は、マシンの構成によって異なります。
このセクションでは、フレームごとのスタートアップ時間、CPU、GPU 時間を測定する方法について説明します。 コンピューター上の同じサンプルのパフォーマンス トレースをキャプチャし、さまざまな測定値の違いを確認できます。
GPUView でトレースを分析するには、GPUView.exeを使用して "merged.elt" ファイルを開きます。
起動時間
起動時間は、アプリの開始からコンテンツが最初に画面に表示されるまでの合計時間で測定されます。
スタートアップ時間の測定は、前のセクションで示した手順に従って、これらのバリエーションを使用して最適に実行されます。
- アプリを初めて起動したときに起動時の測定値を取得する場合は、コールド スタートアップと呼ばれます。 アプリを短時間に数回起動した後の測定と異なる場合があります。 これはウォーム スタートアップと呼ばれます。 起動時にアプリが作成するリソースの数によっては、2 つの起動時間に大きな違いがある可能性があります。 アプリの目標によっては、いずれかを測定することが望ましい場合があります。
- パフォーマンス情報をログに記録するときは、最初のフレームが画面に表示されたらすぐにアプリを終了します。
GPUView を使用した起動時間の計算
GPUView で、関連するプロセス (この場合は GeometryRealization.exe) まで下にスクロールします。
コンテキスト CPU キューは、ハードウェアにキューに登録されているグラフィックス ワークロードを表しますが、必ずしもハードウェアによって処理されるとは限りません。 トレース ファイルを開くと、トレースが取得されてからの間にログに記録されたすべてのイベントが表示されます。 スタートアップ時間を計算するには、関心領域を選択し、Ctrl + Z キーを使用して最初のコンテキスト CPU キューの最初の部分 (これはアクティビティを示すキュー) にズームします。 GPUView コントロールの詳細については、GPUView ヘルプ ファイルの「GPUView コントロールの概要」セクションを参照してください。 次の図は、コンテキスト CPU キューの最初の部分にズームインされた GeometryRealization.exe プロセスのみを示しています。 コンテキスト CPU キューの色はキューのすぐ下の四角形で示され、キュー内の同じカラー データ パケットは、ハードウェアでキューに配置された GPU 作業を示します。 コンテキスト キュー内のハッチ パターン パケットは、現在のパケットを示しています。つまり、アプリは、ハードウェアが画面にコンテンツを表示することを望んでいます。
スタートアップ時間は、コンテキストが最初に表示されるまで (この場合は UI スレッド エントリ ポイント モジュール SHCORE.dll) アプリが最初に起動する時刻です (ハッチ パケットでマークされます)。 ここでの図は、関心のある領域を強調しています。
注
実際の現在の情報はフリップ キューで表されるため、現在のパケットが実際にフリップ キューで完了するまで時間がかかります。
下の図では、完全なステータス バーは表示されません。これは、強調表示された部分間の経過時間も示しています。 これはアプリの起動時間です。 この場合、上記のマシンでは約 240 ミリ秒が発生しました。
CPU と GPU のフレームあたりの時間
CPU 時間を測定する際に考慮すべき点がいくつかあります。 分析するシナリオを実行したトレース内の領域を探します。 たとえば、ジオメトリ実現サンプルでは、分析されているシナリオの 1 つは、レンダリング 2048 と 8192 プリミティブの間の遷移であり、すべて未実現です (ジオメトリはフレームごとにテッセレーションされません)。 トレースは、プリミティブの数の遷移の前後の CPU と GPU アクティビティの違いを明確に示しています。
フレームあたりの CPU 時間と GPU 時間を計算するために、2 つのシナリオが分析されています。 要件は次のとおりです。
- 2048 の未実現プリミティブのレンダリングから、8192 個の未実現プリミティブへの移行。
- レンダリング 8192 で実現されたプリミティブから 8192 個の未実現プリミティブへの移行。
いずれの場合も、フレームレートが大幅に低下することが観察された。 CPU と GPU の時間の測定、2 つの間の関係、およびトレース内の他のいくつかのパターンにより、アプリの問題のある領域に関する有用な情報が得られます。
2048 プリミティブが非現実的にレンダリングされている場合の CPU と GPU 時間の計算
GPUView.exeを使用してトレース ファイルを開きます。
GeometryRealization.exe プロセスまで下にスクロールします。
CPU 時間を計算する領域を選択し、Ctrl + Z キーを使用して拡大します。
F8 キーを切り替えて v 同期情報を表示します。 1 つの vsync 値のデータが明確に表示されるまで拡大し続ける。 青い線は、v-syncのタイミングを示しています。 通常、これらは 16 ミリ秒 (60 fps) ごとに 1 回発生しますが、DWM でパフォーマンスの問題が発生した場合は実行速度が遅くなり、32 ミリ秒 (30 fps) ごとに発生します。 時間を把握するには、1 つの青いバーから次のバーを選択し、 GPUView ウィンドウの右下隅で報告されたミリ秒の数を確認します。
フレームあたりの CPU 時間を測定するには、レンダリングに関係するすべてのスレッドが要する時間の長さを測定します。 パフォーマンスの観点から最も関連性が高いと予想されるスレッドを絞り込む価値があります。 たとえば、ジオメトリの実現サンプルでは、コンテンツがアニメーション化されており、すべてのフレームで画面にレンダリングする必要があるため、UIスレッドが重要になります。 見るスレッドを決定したら、このスレッドのバーの長さを測定します。 これらの一部を平均すると、フレームあたりの CPU 時間が得られます。 次の図は、UI スレッドにかかった時間を示しています。 また、この時間は、2 つの連続する v 同期の間で適切に適合していることも示しています。これは、60FPS に達していることを意味します。
DWM がすべてのフレームを表示できることを示す対応するタイム フレームのフリップ キューを確認することもできます。
GPU 時間は、CPU 時間と同じ方法で測定できます。 CPU 時間を測定する場合と同様に、関連する領域を拡大します。 GPU ハードウェア キュー内のバーの長さを、コンテキスト CPU キューの色と同じ色で測定します。 バーが連続する v 同期内に収まる限り、アプリは 60FPS でスムーズに実行されます。
8192 プリミティブが非現実的にレンダリングされている場合の CPU と GPU 時間の計算
同じ手順をもう一度実行すると、1 つのフレームのすべての CPU 処理が 1 つの v 同期と次のフレームの間に収まらないことがトレースに示されます。 これは、アプリが CPU バインドされていることを意味します。 UI スレッドが CPU を飽和状態にしています。
フリップ キューを見ると、DWM ですべてのフレームを表示できないことも明らかです。
時間が費やされている場所を分析するには、 XPerf でトレースを開きます。 XPerf で起動時間を分析するには、最初に GPUView で時間間隔を見つけます。 間隔の左側と右にマウス を置き、 GPUView ウィンドウの下部に表示される絶対時間をメモします。 次に 、XPerf で同じ .etl ファイルを開き、[CPU による CPU サンプリング] グラフまで下にスクロールし、右クリックして [間隔の選択]を選択します。これにより、GPU トレースを調べることで検出された関心のある間隔で入力できます。
[トレース] メニューに移動し、[シンボルの読み込み] がオンになっていることを確認します。 また、[トレース] -> [シンボル パスの構成] に移動し、アプリのシンボル パスを入力します。 シンボル ファイルには、別のデータベース (.pdb) 内のコンパイル済み実行可能ファイルに関するデバッグ情報が含まれています。 このファイルは、一般に PDB と呼ばれます。 シンボル ファイルの詳細については、シンボル ファイルを参照してください。 このファイルは、アプリ ディレクトリの "デバッグ" フォルダーに配置できます。
アプリで費やされている時間の内訳を取得するには、前の手順で選択した間隔を右クリックし、[概要テーブル] をクリックします。 各 dll に費やされた時間の概要を確認するには、[列] メニューの [スタック] をオフにします。 ここでの "Count" 列は、指定された dll/関数内のサンプルの数を示しています。 ミリ秒あたり約 1 つのサンプルが取得されるため、この数は、各 dll/関数に費やされる時間の最適な推測として使用できます。 [列] メニューで [スタック] をオンにすると、呼び出しグラフ内の各関数に費やされた包括的な時間が表示されます。 これは、問題のポイントをさらに分解するのに役立ちます。
2048 年の未実現プリミティブのスタック トレース情報では、ジオメトリの実現プロセスに 30% の CPU 時間が費やされていることが明らかになります。 その約36% の時間がジオメトリテッセレーションおよびストローク処理に費やされています。
8192 個の未実現プリミティブのスタック トレース情報により、CPU 時間の約 60% (4 コア) がジオメトリの実現に費やされていることが明らかになります。
8192 プリミティブのレンダリングが実現されたときの CPU 時間の計算
プロファイルから、アプリが CPU バインドされていることは明らかです。 CPU で費やされる時間を短縮するために、ジオメトリを 1 回作成してキャッシュできます。 キャッシュされたコンテンツは、フレームあたりのジオメトリ テッセレーション コストを発生させることなく、フレームごとにレンダリングできます。 GPUView でアプリの実現部分のトレースを見ると、DWM がすべてのフレームを表示でき、CPU 時間が大幅に短縮されたことは明らかです。
グラフの最初の部分は、実現された 8192 プリミティブを示しています。 フレームあたりの対応する CPU 時間は、2 つの連続する v 同期内に収まります。 グラフの後の部分では、これは当てはまりません。
XPerf を見ると、CPU は最も長い時間アイドル状態にあり、ジオメトリ実現アプリに費やされる CPU 時間は約 25% です。
概要
GPUView と XPerf の両方と、DirectX アプリのパフォーマンスを分析するための強力なツール。 この記事は、これらのツールを使用し、基本的なパフォーマンス測定とアプリの特性を理解するための入門書です。 ツールの使用状況を理解する以外に、まず分析対象のアプリを理解することが重要です。 まず、アプリが何を達成しようとしているかなどの質問に対する回答を見つけることから始めます。 システムのどのスレッドが最も重要ですか? どのようなトレードオフを行う必要がありますか? パフォーマンス トレースを分析する場合は、まず明らかに問題のある場所を調べることから始めます。 アプリの CPU または GPU はバインドされていますか? アプリはすべてのフレームを表示できますか? ツールとアプリの理解を組み合わせることで、パフォーマンスの問題を理解し、見つけ、最終的に解決するのに非常に役立つ情報を得ることができます。