CPU使用率とは何か

いきなりまとめ

CPU使用率(CPU Usage, %CPU)は、CPU 時間の合計のうち、特定のタスクが占めた割合である。ただし合計時間には CPU が idle 状態の時間も含む。

背景

たとえば PC の動作が重いとき、Windows のタスクマネージャや Linux の top コマンドから CPU 使用率を見ることがある。あるプロセスの CPU 使用率が高いとき、そのプロセスを停止することで PC の動作が改善されたりする。最近 OS を自作していて、CPU 使用率に対する素朴な疑問を解消したくなったのでメモる。

まずは正しそうな定義を見てみる

top コマンドのマニュアルには CPU 使用率について以下のような記述がある。

  1. %CPU -- CPU Usage The task's share of the elapsed CPU time since the last screen update, expressed as a percentage of total CPU time.

最後のスクリーンの更新からの合計 CPU 時間に対するタスクの占有率である、とのこと。まぁこんなもんだろう。

素朴な疑問を解消してゆく

ここからは、自分がこの世に産まれてから CPU 使用率に対して抱いたことのある疑問と回答を列挙する。この世の何かしらの生命にとって参考になれば幸いである。

1つの CPU が複数のタスクに共有されるのはなぜ?

1つのパソコンに複数の CPU が搭載されているのは知っている。そして CPU というのはプログラムを読み込んで、その命令を実行してゆくものである。4つの CPU があるんだったら4つのタスクがこなせそうである。逆に言うと、あるタスクを実行し続けている限りは、そのタスクが CPU 使用率100%を占めるんだろう。しかし実際は CPU 使用率が100%になることなんてまずない。不思議だ。こんなふうに思ってるんだろう、そこのちびっ子よ。

まず、CPU が同時に1つのタスク(プロセス)しか実行できないのは理解として正しい。しかし、CPU は複数のタスクを瞬時に切り替えながら実行を行うことができる。こういうのは Concurrency と呼ばれている。以下の図には concurrency の例が3つ載っている。1つの CPU がピンク色と青色のタスクを瞬時に切り替えながら実行するため、人間にとっては複数のタスクが同時に実行されているように見える。

f:id:t-keita:20211118005722p:plain:w600

(※画像は このページ から引用した)

以上の話で、1つの CPU が複数のタスクに共有されるため、CPU 使用率が複数のタスクに割り振られることがイメージできただろう。疑問が解消された。めでたし。

ちなみに concurrency は「並行」と訳される。parallelism の「並列」という言葉と混同されがちなので英語のまま concurrency と parallelism で覚えよう。

CPU 使用率の合計が100%未満になるのはなぜ?

CPU 使用率は全体に対してそのタスクが占めた時間の割合であった。そのため、すべてのタスクの CPU 使用率を合計すると100%になると考えるのが妥当だろう。しかし実際は CPU 使用率が100%になることはほぼない。20%とか60%とかそんなもんだろう。

まず、CPU には idle という状態が存在する。これは CPU が与えられたすべてのタスクを終えて停止している状態である。消費電力を抑える狙いがある。たとえば、x86 アセンブリでは HLT 命令が実行されると CPU が idle 状態になる。次なるタスクが与えられると CPU が目を覚まして実行を再開する。

そして、CPU 使用率の計算には idle 状態の時間はどのタスクにも占有されていないと捉えられる。これがすべてのタスクの CPU 使用率を合計しても100%未満にしかならない原因である。

ちなみに、CPU Utilization is Wrong という有名な記事では、CPU 使用率は「idle 状態でない時間」を指すものであり、必ずしも「実際にタスクが実行されている時間」を指すものではないという指摘がある。以下の図がその例である。

f:id:t-keita:20211118011548p:plain

タスクが実行されている "Busy状態" と CPU が停止している "idle状態" に加えて "stalled状態" がある。stalled とはメモリの読み書きなどを待つ状態を指しており、その間は命令の実行が進まないらしい。

(一部修正 2022.01)

参考