DirectX アプリのプロファイリング
ここでは、Windows Performance Toolkit の一部として提供される XPerf ツールと GPUView ツールを使用して、DirectX アプリの最も重要なパフォーマンス時間測定の一部を測定する方法を示します。 これは、ツールを理解するための包括的なガイドではなく、DirectX アプリのパフォーマンスを分析するための具体的な適用性です。 ここで説明する手法のほとんどはすべての DirectX アプリに関連しますが、スワップ チェーンを使用するアプリに最も関連しており、SIS/VSIS と XAML アニメーションを使用する XAML 上に構築された DirectX アプリケーションには関連しません。 主要なパフォーマンス時間測定、ツールを取得してインストールする方法、パフォーマンス測定トレースを取得し、それらを分析してアプリのボトルネックを理解する方法について説明します。
ツールについて
Xperf
XPerf は、詳細なシステムとアプリのパフォーマンスとリソースの使用状況を測定および分析するために設計された、Windows イベント トレーシング (ETW) の上に構築された一連のパフォーマンス分析ツールです。 Windows 8以降、このコマンド ライン ツールにはグラフィカル ユーザー インターフェイスがあり、Windows Performance Recorder (WPR) と Windows パフォーマンス アナライザー (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 ソフトウェア開発キット (SDK) for Windows の一部として提供されています。 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) を保存します。
測定
Note
ジオメトリ実現サンプルの測定値は、DirectX11 グラフィックス カードを統合した Quad Core マシンで取得されます。 測定は、マシンの構成によって異なります。
このセクションでは、フレームごとのスタートアップ時間、CPU、GPU 時間を測定する方法について説明します。 マシン上の同じサンプルのパフォーマンス トレースをキャプチャし、さまざまな測定値の違いを確認できます。
GPUView でトレースを分析するには、 を使用して "merged.elt" ファイルGPUView.exe開きます。
スタートアップ時
起動時間は、アプリの開始からコンテンツが最初に画面に表示されるまでに費やされた合計時間によって測定されます。
スタートアップ時の測定は、前のセクションで示した手順に従って、これらのバリエーションを使用して行うのが最適です。
- アプリを初めて起動するときにスタートアップ測定を行う場合は、コールド スタートアップと呼ばれます。 これは、アプリを数回起動した後に短時間で行われた測定値とは異なる場合があります。 これはウォーム スタートアップと呼ばれます。 起動時にアプリが作成するリソースの数によっては、2 つのスタートアップ時間に大きな違いがある可能性があります。 アプリの目標によっては、いずれかを測定することが望ましい場合があります。
- パフォーマンス情報をログに記録するときは、最初のフレームが画面に表示されたらすぐにアプリを終了します。
GPUView を使用した起動時間の計算
GPUView で、関連するプロセス (この場合はGeometryRealization.exe) まで下にスクロールします。
コンテキスト CPU キューは、ハードウェアにキューに入れられているグラフィックス ワークロードを表しますが、必ずしもハードウェアによって処理されるわけではありません。 トレース ファイルを開くと、トレースが取得されてからの間にログに記録されたすべてのイベントが表示されます。 スタートアップ時間を計算するには、目的の領域を選択し、Ctrl + Z キーを使用して最初のコンテキスト CPU キュー (これはアクティビティを示すキュー) の最初の部分にズームします。 GPUView コントロールの詳細については、「GPUView のヘルプ ファイル」セクション「GPUView コントロールの概要」を参照してください。 次の図は、コンテキスト CPU キューの最初の部分にズームインされたGeometryRealization.exe プロセスのみを示しています。 コンテキスト CPU キューの色はキューのすぐ下の四角形で示され、キュー内の同じカラー データ パケットは、ハードウェアでキューに配置された GPU 作業を示します。 コンテキスト キュー内のハッチ パターン パケットは、現在のパケットを示しています。つまり、アプリは、ハードウェアが画面にコンテンツを表示することを望んでいます。
スタートアップ時間は、コンテキストが最初に表示されるまで (この場合は UI スレッド エントリ ポイント モジュール SHCORE.dll) アプリが最初に起動する時刻です (ハッチ パケットでマークされます)。 ここでの図は、関心のある領域を強調しています。
Note
実際の現在の情報はフリップ キューで表されるため、現在のパケットが実際にフリップ キューで完了するまでの時間が長くなります。
下の図では、完全なステータス バーは表示されません。これは、強調表示された部分間の経過時間も示しています。 これは、アプリの起動時間です。 この場合、上記のマシンでは、約 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 同期時間の場所です。 通常、これらは 16 ミリ秒 (60 fps) ごとに 1 回発生しますが、DWM でパフォーマンスの問題が発生している場合は、実行速度が遅くなり、32 ミリ秒 (30 fps) ごとに 1 回発生します。 時間の感覚を得るには、青いバーから次のバーを選択し、 GPUView ウィンドウの右下隅で報告されたミリ秒の数を確認します。
フレームあたりの CPU 時間を測定するには、レンダリングに関係するすべてのスレッドによって実行される時間の長さを測定します。 パフォーマンスの観点から最も関連性が高いと予想されるスレッドを絞り込む価値があります。 たとえば、geometry の実現サンプルでは、コンテンツはアニメーション化されており、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 と呼ばれます。 シンボル ファイルの詳細については、 シンボル ファイルに関するページを参照してください。 このファイルは、アプリ ディレクトリの "Debug" フォルダーにあります。
アプリで費やされている時間の内訳を取得するには、前の手順で選択した間隔を右クリックし、[概要テーブル] をクリックします。 各 dll で費やされた時間の概要を確認するには、[列] メニューから [スタック] をオフにします。 ここでの "Count" 列には、指定された dll/関数内のサンプルの数が示されていることに注意してください。 ミリ秒あたり約 1 つのサンプルが取得されるため、この数は、各 dll/関数に費やされる時間の最適な推測として使用できます。 [列] メニューの [スタック] をオンにすると、呼び出しグラフの各関数に費やされた包括時間が与えられます。 これは、問題のポイントをさらに分解するのに役立ちます。
2048 の未実現プリミティブのスタック トレース情報により、ジオメトリ実現プロセスに CPU 時間の 30% が費やされていることが明らかになります。 そのうち約36%の時間がジオメトリテセレーションとストロークに費やされています。
8192 個の未実現プリミティブのスタック トレース情報では、CPU 時間 (4 コア) の約 60% がジオメトリの実現に費やされていることが明らかになります。
8192 プリミティブのレンダリングが実現されている場合の CPU 時間の計算
アプリが CPU バインドされていることは、プロファイルから明らかです。 CPU によって費やされる時間を短縮するために、ジオメトリを 1 回作成してキャッシュできます。 キャッシュされたコンテンツは、フレームあたりのジオメトリ テセレーション コストを発生させることなく、すべてのフレームにレンダリングできます。 GPUView でアプリの実現部分のトレースを見ると、DWM はすべてのフレームを表示でき、CPU 時間が大幅に短縮されたことは明らかです。
グラフの最初の部分は、実現された 8192 プリミティブを示しています。 フレームあたりの対応する CPU 時間は、2 つの連続する v 同期内に収まります。 グラフの後の部分では、これは正しくありません。
XPerf を見ると、CPU は最も長い時間アイドル状態にあり、CPU 時間の約 25% のみがジオメトリ実現アプリに費やされています。
まとめ
GPUView と XPerf の両方と、DirectX アプリのパフォーマンスを分析するための強力なツール。 この記事は、これらのツールを使用し、基本的なパフォーマンス測定とアプリの特性を理解するための入門書です。 ツールの使用状況を理解する以外に、まず分析対象のアプリを理解することが重要です。 アプリが何を達成しようとしているかなどの質問に対する回答を見つけることから始めますか? システムのどのスレッドが最も重要ですか? どのようなトレードオフを行う必要がありますか? パフォーマンス トレースを分析する場合は、まず明らかな問題のある場所を調べることから始めます。 アプリの CPU または GPU はバインドされていますか? アプリはすべてのフレームを表示できますか? ツールとアプリの理解を組み合わせることで、パフォーマンスの問題を理解し、見つけ、最終的に解決するのに非常に役立つ情報を得ることができます。