5/11/2017

CPUの使用率は間違っている

ブレンダン・グレッグ氏のブログより。

我々がCPU使用率に利用するメトリック(測定基準)は深刻な誤解を招き、毎年悪化している。CPU使用率とは何か? プロセッサはどのくらい忙しいのか? いいえ、それは測定できるものではない。そう、私は、どこでも誰にでも使用される"%CPU"メトリックに関して話している。全ての性能監視ツールで。top(1)で。

90%のCPU使用率が意味するもの: Cpubusyidle

実際の意味は:

Cpubusystalledidle

Stalledは、プロセッサが命令の進行を進めていないことを意味し、通常はメモリI/O待ちになっているために発生する。私が上で描いた比率(busyとstalledの間)は、通常はツールの中で見るものである。可能性はほとんどstalledだが、それを知らない。

これはあなたにとってどういう意味があるのか? どのくらいCPUがストールしているのか理解することはコードの削減やメモリI/Oの削減の間でパフォーマンス・チューニングに向けることができる。特にクラウド上で、CPUに基づくオートスケールのためにCPU使用率を見ている人は、%CPUのストールしたコンポーネントを知ることで利益を得るだろう。

実際にCPU利用率は何だ?

CPU使用率と呼ばれるメトリックは実際には"非アイドル時間"であ。つまり、CPUがアイドル状態のスレッドを実行していない時間である。オペレーティング・システムのカーネル(それが何であれ)は通常、コンテキストスイッチの間はこれをトラックしない。非アイドル状態のスレッドが実行し始め、100ミリ秒後に停止すると、カーネルはCPUがその全体の時間を利用したと考える。

このメトリックはタイム・シェアリング・システムと同じくらい古い。アポロ月着陸船の誘導コンピュータ(タイム・シェアリング・システムの先駆け)は、アイドル状態のスレッドを"DUMMY JOB"と呼んでいた。そして、エンジニアはそれを実行するサイクルをトラックし、重要なコンピュータ使用率のメトリックとして実際のタスクと比較した(私は以前これについて書いた)。

それで、これの何が間違っているのか?

現在、CPUはメインメモリよりもはるかに高速化されており、メモリを待つことが今だ"CPU使用率"と呼ばれるものを支配している。top(1)の%CPUが高いと、実際はDRAMのバンクであっても、あなたはボトルネックになっているプロセッサ(ヒートシンクとファンの下のCPUパッケージ)のことを考えるかも知れない。

これは悪化している。長い間、プロセッサメーカーはDRAMよりもクロック速度を速くし、アクセス・レイテンシ(CPUとDRAMのギャップ)を拡大させてきた。2005年頃には3GHzのプロセッサで平準化され、プロセッサはより多くのコアとハイパースレッドに加え、マルチソケット構成で拡大され、全体でメモリサブシステムへの更なる要求が高まっている。プロセッサメーカは、より大きくよりスマートなCPUキャッシュ、高速なメモリバスや相互接続で、このメモリのボトルネックを低減しようとしている。しかし、我々はいまだ普通にストールしてしまう。

CPUが実際にしていることを知る方法

Performance Monitoring Counters (PMCs)を使うことで、Linux perfや他のツールを使ってハードウェアカウンタを読み取ることができる。例えば、システム全体を10秒間測定すると次のようになる:


# perf stat -a -- sleep 10

 Performance counter stats for 'system wide':

     641398.723351      task-clock (msec)         #   64.116 CPUs utilized            (100.00%)
           379,651      context-switches          #    0.592 K/sec                    (100.00%)
            51,546      cpu-migrations            #    0.080 K/sec                    (100.00%)
        13,423,039      page-faults               #    0.021 M/sec                  
 1,433,972,173,374      cycles                    #    2.236 GHz                      (75.02%)
         stalled-cycles-frontend  
         stalled-cycles-backend   
 1,118,336,816,068      instructions              #    0.78  insns per cycle          (75.01%)
   249,644,142,804      branches                  #  389.218 M/sec                    (75.01%)
     7,791,449,769      branch-misses             #    3.12% of all branches          (75.01%)

      10.003794539 seconds time elapsed

ここで重要なメトリックは、1サイクルあたりの命令数(issns per cycle: IPC)で、CPUクロックサイクル毎に完了した命令の平均数を示している。高いほど良い(単純に)。上記の0.78の例は、あなたはプロセッサの最高速度が4.0というIPCだと気付くまで悪くはない(78% busy?)。これは4-wideとして知られていて、命令のフェッチ/デコード・パスを参照している。つまり、CPUはクロックサイクル毎に4つの命令をリタイア(完了)できる。従って、4-wideシステムでの0.78のIPCは、CPUが最高速度で19.5%で動作していることを意味する。新しいインテルのSkylakeプロセッサは5-wideである。

さらに掘り下げるのに数百ものPMCがある: ストールされるサイクルは異なるタイプで直接測定する。

クラウドでは

仮想環境にいるなら、ハイパーバイザがゲストをサポートするかどうかに依存し、PMCへのアクセスができない場合がある。私は最近EC2のPMCについて: IPCを計測投稿した: PMCがどのように見えるかは、AWS EC2のXenベースのクラウド上で専用ホストタイプでは利用可能であることを示した。

解釈とすぐに実施可能な項目

IPCが1.0未満だと、メモリーがストールしている可能性が高く、メモリI/Oを減らし、CPUキャッシュとメモリの局所性を改善する(特にNUMAシステムで)を含めてソフトウェアのチューニング戦略を立てる。ハードウェアチューングは、大きなCPUキャッシュを持つプロセッサ、高速なメモリやバス、インターコネクトを使うことである。

IPCが1.0より大きい場合、命令が縛られている(instruction bound)可能性が高い。コードの実行を減らす方策を探して欲しい: 不必要な作業やキャッシュ操作などを取り除く。CPUのフレームグラフはこの調査に役立つ素晴らしいツールである。ハードウェアのチューニングには、高速なクロックレートやコア数やハイパースレッド数を増やす。

上記のルールで、私はIPCを1.0に分配している。それをどこから得たのか? 私は前のPMCの作業に基づいて作成した。あなた向けのシステムとランタイムに合わせてカスタム値を得る方法は次の通り: 一つはCPUバウンド、もう一つはメモリバウンドの2つのダミー作業負荷を書く。そして、IPCを測定し、その中間点を計算する。

性能監視製品はあなたに何を告げているのか

全てのパフォーマンスツールは%CPUと共にIPCを表示するべきだ。あるいは、%CPUを命令リタイアサイクルとストールサイクルに分解する。例えば、%INSや%STL。

top(1)に関して、Linuxにはプロセス毎にIPCを表示するtiptop(1)がある:


tiptop -                  [root]
Tasks:  96 total,   3 displayed                               screen  0: default

  PID [ %CPU] %SYS    P   Mcycle   Minstr   IPC  %MISS  %BMIS  %BUS COMMAND
 3897   35.3  28.5    4   274.06   178.23  0.65   0.06   0.00   0.0 java
 1319+   5.5   2.6    6    87.32   125.55  1.44   0.34   0.26   0.0 nm-applet
  900    0.9   0.0    6    25.91    55.55  2.14   0.12   0.21   0.0 dbus-daemo

CPU使用率が誤解を招く他の理由

CPU使用率が誤解を招く原因はメモリのストールサイクルだけではない。その他の要因は:

  • 温度がプロセッサのストーリングを誤らせる
  • ターボブーストがクロックレートを変える
  • カーネルがスピードステップでクロックレートを変える
  • 平均の問題: 1分で80%の使用率が、100%のバーストを隠してしまう
  • スピンロック: 高いIPCでCPUが利用されるが、アプリは論理的に実行が進まなくなる

まとめ

CPU使用率は大きく誤解を招くようなメトリックになっている: メインメモリに待機するサイクルを含み、今の作業負荷に影響を及ぼす事ができる。サイクル毎の命令(IPC)を含み、追加メトリックを使って、%CPUが実際に示しているものを把握できる。IPCが1.0を超える場合はメモリ境界を意味し、IPCが1.0未満の場合は命令境界を意味する。以前の記事で、IPCを測定するために必要なパフォーマンス・モニタリング・カウンタ(PMC)を紹介するなど、IPCを取り上げた。

CPUの負荷量全ての%CPUを示すパフォーマンス監視ツールには、エンドユーザに誤解を与えないように、その意味を説明するためPMCメトリックを表示する必要もある。例えば、IPC、命令リタイア・サイクル対ストール・サイクルを示す事ができる。これらのメトリックを活用する事で、開発者や運用者は、アプリケーションやシステムのチューニング方法を選択できる。

Hacker News