CPU と GPU のフレーム処理時間を見積もる

アプリのパフォーマンスを把握してボトルネックを見つけるには、CPU と GPU のフレーム処理時間(フレーム時間)を推定することが不可欠です。AGI でアプリをプロファイリングすると、System Profiler からフレーム時間の推定に使用できるトレースデータが提供されます。

CPU 時間

AGI では、システム プロファイルの CPU トラックで CPU フレームの合計時間とアクティブ時間を表示できます。

合計 CPU 時間

費やされた合計 CPU 時間を測定するには、 連続するフレーム送信イベント間の時間を含む 期間を選択します。フレーム送信イベントは eglSwapBuffers(OpenGL の場合)と vkQueuePresentKHR(Vulkan の場合)です。

eglSwapBuffer イベントのスクリーンショット。
図 1.2 つの eglSwapBuffer イベント間の時間。


vkQueuePresentKHR イベントのスクリーンショット。
図 2.2 つの vkQueuePresentKHR イベント間の時間。

この測定値は合計 CPU 時間の推定値ですが、必ずしもアクティブな CPU 時間を表すものではありません。たとえば、GPU バウンドのアプリでは、CPU は GPU が処理を完了してから新しいフレームを送信するまで待機することがあります。これは、dequeueBuffereglSwapBuffer(OpenGL の場合)、vkQueuePresent(Vulkan の場合)のイベントが CPU 時間の大部分を占めている場合に発生することがよくあります。 待機時間は合計 CPU 時間に含まれますが、アクティブな CPU 時間には含まれません。

dequeueBuffer イベントと eglSwapBuffer イベントの間に大量のアイドル状態が発生していることを示すスクリーンショット。
図 3. dequeueBuffer イベントと eglSwapBuffer イベント中に CPU がアイドル状態になっている時間が長い。

アクティブな CPU 時間

アクティブな CPU 時間は、CPU がアイドル状態にならずにアプリのコードを実行している時間を決定します。

アクティブな CPU 時間を測定するには、CPU イベントのすぐ上にある [Running] スライスを表示します。2 つのフレーム送信イベント間のトレースのすべての部分をカウントします。これらの部分は、実行中の状態です。ワーカースレッドを含めるようにしてください。

アクティブな CPU 時間の測定に使用できる 2 つの期間の CPU 時間のスクリーンショット。
図 5.アクティブな CPU 時間の測定に使用できる 2 つの CPU 時間。


メインスレッドがアイドル状態のときに他のワーキング スレッドがあるマルチスレッド アプリのスクリーンショット。
図 6.メインスレッドがアイドル状態のときに他のワーカースレッドがあるマルチスレッド アプリ。

アクティブな CPU 時間を測定するもう 1 つの方法は、CPU トラックでアプリのスライスを表示することです。これらのスライスは、CPU が実行されている時間を示し、[Running] スライスに対応しています。

CPU トラックと一致する固定スレッドの実行状態を示すスクリーンショット。
図 7.固定されたスレッドの実行状態が CPU トラックと一致している。

アプリのスライスを特定するには、アプリに ATrace マーカーを追加します。これにより、System Profiler の CPU トラックにマーカーが表示されます。

CPU トラックに表示された ATrace スライスのスクリーンショット。
図 8.CPU トラックに表示された ATrace スライス。

GPU フレーム時間を推定する

GPU フレーム時間を推定するには、System Profiler で GPU スライスまたは GPU カウンタを使用します。GPU スライスを使用すると、推定の精度が向上します。

GPU スライス

System Profiler で GPU スライス情報が利用可能な場合は、アプリが 1 つのフレームに関連付けられたタスクの処理に費やす合計時間を測定することで、非常に正確な GPU フレーム時間情報を取得できます。

Mali デバイス

Mali デバイスでは、GPU スライスに [fragment]、[non-fragment]、場合によっては [supplementary non-fragment] トラックがあります。複雑でないフレームの場合、フラグメントと非フラグメントの処理は順次行われるため、アクティブな GPU 処理のギャップを探すことで、あるフレームの処理を別のフレームの処理と区別できます。

別の方法として、GPU に送信される処理に精通している場合は、送信されたレンダーパスのパターンを特定することで、フレームの開始と終了に関する情報を取得できます。

複数のフレームが順番に実行されているスクリーンショット。
図 9.複数のフレームが順番に実行されている。
AGI が個々のフレームの作業にズームインしているスクリーンショット。
図 10.個々のフレームの処理を拡大表示。

GPU ワークフローが高度に並列化されているアプリの場合は、各スライスの [Selection] ペインで同じ submissionID を持つすべてのフレームを探すことで、GPU フレーム時間を取得できます。

Vulkan ベースのアプリでは、複数の送信を使用してフレームを構成できます。送信 ID を追跡するには、送信ごとにスライスを含む [Vulkan Events] トラックを使用します。送信スライスを選択すると、送信に対応するすべての GPU アクティビティ スライスがハイライト表示されます。

並列化された GPU ワークロードのスクリーンショット。1 つのフレームの処理が別のフレームの処理と重複する可能性があります。
図 11.並列化された GPU ワークロード。1 つのフレームの処理が別のフレームの処理と重複する可能性がある。


フレーム用に選択された複数の Vulkan イベントのスクリーンショット。
図 12.フレームに対して選択された複数の Vulkan イベント。

Adreno デバイス

Adreno デバイスでは、GPU スライスは [GPU Queue 0] トラックに表示され、常に順番に表示されるため、フレームのレンダーパスを表すスライスをすべて確認して、GPU フレーム時間を測定できます。

複数のフレームが順番に実行されているスクリーンショット。
図 13.複数のフレームが順番に実行されている。
複数のレンダリング パスを含むフレームが拡大表示された AGI のスクリーンショット。
図 14.複数のレンダーパスを含むフレームを拡大表示。

前述の Mali のシナリオと同様に、アプリが Vulkan を使用している場合、[Vulkan Events] トラックには、フレームを実行するために送信される処理に関する情報が表示されます。レンダーパスをハイライト表示するには、フレームに関連付けられている [Vulkan Events] スライスをクリックします。

フレームの Vulkan イベントが選択されている Vulkan ベースのアプリのスクリーンショット。
図 15.フレームの Vulkan イベントが選択されている Vulkan ベースのアプリ。

アプリが GPU バウンドであるため、GPU フレームの境界を区別するのが難しいシナリオがあります。このようなシナリオでは、GPU に送信される処理に精通している場合は、レンダーパスが実行されるパターンを特定し、その情報からフレームの境界を判断できます。

フレーム境界の特定に役立つレンダーパス パターンを含む、GPU バウンドの重いアプリのスクリーンショット。
図 16.フレームの境界を特定するのに役立つレンダーパス パターンを持つ、GPU バウンドのアプリ。

GPU カウンタ

トレースで GPU スライス情報が利用できない場合は、[GPU counter] トラックを使用して GPU フレーム時間を推定できます。

Mali デバイス

Mali デバイスでは、[GPU utilization] トラックを使用して、GPU 負荷が高くないアプリの GPU フレーム時間を推定できます。GPU 負荷が低いアプリでは、アクティビティが常に高いのではなく、GPU アクティビティが高い期間と低い期間が定期的に発生します。[GPU utilization] トラックを使用して GPU フレーム時間を推定するには、トラック内のアクティビティが高い期間の長さを測定します。

Mali デバイスの GPU 使用率と GPU キューのトラックのスクリーンショット。
図 17.Mali デバイスの GPU 使用率と GPU キューのトラック。

アプリの GPU 使用率が高い場合、GPU 使用率は常に非常に高くなる可能性があります。この場合は、fragment queue utilization トラックと non-fragment queue utilization トラックを使用して GPU アクティビティをモニタリングし、GPU フレーム時間を推定できます。[fragment] トラックと [non-fragment] トラックのパターンを確認することで、フレームの境界のおおよその位置を把握し、それを使用して GPU フレーム時間を測定できます。

フラグメント トラックと非フラグメント トラックのスクリーンショット。
図 18.[Fragment] トラックと [non-fragment] トラック。

Adreno デバイス

Adreno デバイスで、アプリの GPU 負荷が高くない場合は、前のセクションの Mali デバイスと同じ方法で GPU フレーム時間を推定できます。

Adreno デバイスの GPU 使用率と GPU キューのトラックのスクリーンショット。
図 19.Adreno デバイスの GPU 使用率と GPU キューのトラック。

アプリの GPU 負荷が高く、GPU 使用率が常に高い場合は、[Vertex Instructions / Second] トラックと [Fragment Instructions / Second] トラックを使用して GPU フレーム時間を推定できます。これらのトラックのアクティビティ レベルのパターンを確認することで、フレームの境界のおおよその位置を把握し、それを使用して GPU フレーム時間を測定できます。

Vertex の手順 / セカンド トラックのスクリーンショット。
図 20.[Vertex Instructions / Second] トラック。

他のトラックでも同様の情報が得られる場合があります。

  • Vertices Shaded / Second
  • Fragments Shaded / Second
  • % Time Shading Vertices
  • % Time Shading Fragments