容量に関連するジャンクを特定する

容量とは、デバイスがある程度の時間にわたって占有するリソース(CPU や GPU など)の総量です。このページでは、容量に関連するジャンクの問題を特定して対処する方法を説明します。

ガバナーの反応が遅い

ジャンクを防ぐには、CPU 周波数ガバナーが爆発的なワークロードに迅速に対応できることが必要です。ほとんどの UI アプリは、次のような同一の基本パターンに従います。

  1. ユーザーが画面を閲覧します。
  2. ユーザーが画面にタッチします(ボタンのタップや画面のスクロールなど)。
  3. 画面がスクロール表示され、アクティビティが変更されるか、または入力に応じてなんらかの方法でアニメーションが動作します。
  4. 新しいコンテンツが表示されると、システムは静止します。
  5. ユーザーが画面の閲覧に戻ります。

Pixel および Nexus デバイスには、タッチに応じて CPU 周波数ガバナー(とスケジューラ)の動作を変更するタッチブーストが実装されています。高いクロック周波数への低速の移行(タッチ時にデバイスでフレーム落ちが起こる可能性があります)を避けるために、通常、タッチブーストでは CPU 周波数の下限を設定して、タッチ時に十分な CPU 容量を使用できるようにしています。下限は、タッチ後しばらくの間(通常は約 2 秒)維持されます。

また、Pixel は、Energy Aware Scheduling(EAS)により提供される schedtune cgroup を追加のタッチブースト信号として使用します。トップアプリは schedtune を介して追加の重み付けを取得し、高速の実行に必要な CPU 容量を確保します。Nexus 5X および 6P では、Kryo CPU を搭載した Pixel よりも、小さな CPU クラスタと大きな CPU クラスタ(それぞれ A53 と A57)のパフォーマンス格差がはるかに大きくなっています。小さな CPU クラスタは、特にデバイス上のジッターに他の原因がある場合、スムーズな UI レンダリングを行うのに十分であるとは限らないことがわかりました。

したがって、Nexus 5X および 6P では、タッチブーストによりスケジューラの動作を変更し、フォアグラウンド アプリが大きなコアに移動する確率を高めています(これは、コンセプトとしては CPU 周波数の下限に似ています)。フォアグラウンド アプリが大きな CPU クラスタに移動する確率が高くなるようにスケジューラを変更しないと、スケジューラがスレッドを大きな CPU コアに負荷分散することを決定しない限り、フォアグラウンド アプリのレンダリングのための CPU 容量が不足する可能性があります。タッチブースト時にスケジューラの動作を変更することで、UI スレッドが直ちに大きなコアで実行されてジャンクが回避される確率が高まります。また、常に大きなコアでの実行を強制して電力消費に深刻な影響を及ぼすこともありません。

サーマル スロットリング

デバイスの全体的な熱出力を下げる必要が生じると(一般的には CPU、GPU、DRAM のクロック数を減らすことで実現します)、サーマル スロットリングが発生します。そうすると、特定のタイムスライス内でレンダリングを行うのに十分な容量をシステムが提供できなくなるため、当然ながらしばしばジャンクが発生します。サーマル スロットリングを回避する唯一の方法は、消費電力を減らすことです。これを行う手段は限られていますが、Google の過去の SOC に関する経験から、システム ベンダーにおすすめしたい方法がいくつかあります。

第 1 の方法は、異種 CPU アーキテクチャを使用して新しい SOC を構築する際に、CPU クラスタのパフォーマンス曲線と W 曲線が重なるようにすることです。プロセッサ全体のパフォーマンス曲線と W 曲線は最初から最後まで連続した線でなければなりません。パフォーマンス曲線 / W 曲線が不連続である場合、スケジューラと周波数ガバナーはワークロードが必要とする容量を推測するよう強いられます。ジャンクを防ぐために、スケジューラと周波数ガバナーはワークロードに必要以上の容量を誤って割り当ててしまいます。この結果、電力が過剰に消費されて、サーマル スロットリングが発生します。

CPU クラスタが 2 つある仮定上の SOC を想像してください。

  • クラスタ 1 は小さなクラスタで、100~300 mW を消費し、スループットのベンチマーク スコアはクロックに応じて 100~300 に達します。
  • クラスタ 2 は大きなクラスタで、1,000~1,600 mW を消費し、同じスループットのベンチマーク スコアはクロックに応じて 800~1,200 に達します。

このベンチマークでは、スコアが高いほど高速です。低速であることは望ましくありませんが、高速になるほど電力消費が増加します。

UI ワークロードでベンチマーク スコア 310 に相当するスループットが必要であるとスケジューラが判断した場合、ジャンクを防ぐための最良のオプションは、大きなクラスタを最低の周波数で実行することであり、そうすると大量の電力が浪費されます(これは、cpuidle の動作とアイドル状態への移行に左右されます。連続するパフォーマンス曲線 / W 曲線を持つ SOC は最適化が容易です)。

第 2 の方法は、cpuset を使用することです。カーネルと BoardConfig.mk で cpuset を有効にします。デバイス固有の init.rc で実際の cpuset の割り当ても設定する必要があります。一部のベンダーは、スケジューラの動作に影響を与える他のヒントを使用できることを期待して、BSP でこれを無効のままにしていますが、これは意味がないと思われます。cpuset は、ユーザーによるデバイス上の実際の操作を反映しつつ CPU 間の負荷分散を確実に行えるようにするうえで有用です。

ActivityManager は、アプリ(トップ、フォアグラウンド、バックグラウンド)の相対的な重要性に基づいて各アプリを異なる cpuset に割り当て、重要性の高いアプリが CPU コアにアクセスできる機会を増やします。これにより、フォアグラウンド アプリとトップアプリのサービス品質を確保できます。

cpuset は同種 CPU 構成で有用ですが、異種 CPU 構成のデバイスを出荷する場合も cpuset を有効にしてください。Nexus 6P は、異種 CPU 構成で cpuset を使用する方法を示す良い見本です。各自のデバイス構成の基礎としてご使用ください。

また、cpuset は、パフォーマンスが重視されないバックグラウンド スレッドが大きな CPU コアに負荷分散される(この場合、ユーザーがメリットを感じるわけではないのに大量の電力を消費する可能性がある)状況を回避することで、電力消費を効率化します。これは、サーマル スロットリングを回避するためにも役立ちます。サーマル スロットリングは容量に関する問題ですが、ジッターの改善はサーマル スロットリング時の UI パフォーマンスに多大な影響を与えます。システムの実行能力が 60 FPS のレンダリング能力に近づくため、フレーム落ちの原因となるジッターが少なくなります。