私たちが開発している一部のハードウェアで非常に奇妙な動作を経験しています。私の設定は、デュアルコアiMX6 CPUにSMPとPREEMPT RTを搭載したLinux 4.9.87で構成されています。
この設定で実行されるアプリケーションは、SCHED_FIFOスケジューリングポリシーを使用して実行される3つのスレッドで構成されています。優先順位レベル10、20、30はCPU0にバインドされます。 4番目のスレッドは、同じ予約ポリシーと優先順位90を使用してCPU1で実行されます。
私が経験する行動は次のとおりです。
プロセスを監視すると、topはCPU0が97.4%の時間アイドル状態であることを示します。そのコアで実行されている最も忙しいスレッドには8.4%が必要です。これは5.8%の違いです。
以下は、SolarisモードのCPU固有およびスレッド固有の使用量を示す最上位出力です。
top - 13:36:41 up 1:21, 2 users, load average: 0.52, 0.39, 0.26
Threads: 128 total, 2 running, 126 sleeping, 0 stopped, 0 zombie
%Cpu0 : 1.3 us, 1.3 sy, 0.0 ni, 97.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 509348 total, 438164 free, 46888 used, 24296 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 450196 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
798 root -91 0 37740 35656 3676 S 9.3 7.0 0:04.47 myprog
797 root -31 0 37740 35656 3676 S 8.4 7.0 0:04.43 myprog
241 root -51 0 0 0 0 R 4.7 0.0 3:55.11 irq/26-2014+
242 root rt 0 0 0 0 S 3.1 0.0 2:33.62 spi3
796 root -21 0 37740 35656 3676 S 1.9 7.0 0:01.14 myprog
794 root 20 0 2848 1892 1536 R 1.0 0.4 0:01.04 top
795 root -11 0 37740 35656 3676 S 0.3 7.0 0:00.37 myprog
3 root 20 0 0 0 0 S 0.2 0.0 0:09.14 ksoftirqd/0
10 root 20 0 0 0 0 S 0.2 0.0 0:00.14 rcuc/0
545 root -51 0 0 0 0 S 0.2 0.0 0:03.74 irq/36-can0
595 root 20 0 1700 880 824 S 0.2 0.2 0:00.99 rngd
1 root 20 0 1712 1168 1104 S 0.0 0.2 0:01.34 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
4 root -2 0 0 0 0 S 0.0 0.0 0:07.99 ktimersoftd+
5 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0
6 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
スレッドあたりの使用量は正しいように見えますが、合計はCPUあたりの使用量と一致しません。
htop
これは同じ動作を示すため、top自体に問題はありません。 /proc/stat の値を使用して読み込んで計算しても、top と htop で示したのと同じ結果が得られます。
PID 798
clock_nanosleep()を使用して、500マイクロ秒ごとに優先順位の最も高いスレッド()を予約します。 10ミリ秒ごとにスレッドを予約しようとすると、CPU使用率全体が大幅に減少しますが、数字はまだ一致せず、同じ動作を示します。これは、現在設定されている低周期時間によって問題が発生しないことを示します。
ライブパッチなしでストック配布カーネルでアプリケーションを実行すると、同様の結果が得られます。また、問題がライブパッチにないことを示します。
シングルコアCPUでアプリケーションを再実行しようとすると、同様の結果が得られます。これは、マルチコア設定の実行によって問題が発生しなかったことを示します。
- 以前同様の経験をした人はいますか?
- 各スレッドのCPU使用量の合計が合計と一致しない理由を知っている人はいますか?
- 合計CPU使用率の信頼できる値をどのように取得できますか?
よろしくお願いします!
編集する
この問題を内部的にさらに議論した結果、これが過小サンプリング問題である可能性があると疑われます。
カーネルが定期的にCPU状態(ユーザースペース、カーネルスペース、またはアイドル)をサンプリングすると仮定すると、より多くのサンプルが収集され、スレッドが頻繁に予約されないほど、結果はより正確になります。
また、サンプルがタイマティックから収集されたと仮定し、カーネルのCONFIG_HZを100Hzから1000Hzに増やし、100msごとにスレッドを予約するようにアプリケーションを変更しました。約50%の負荷平均を達成するためにカウンタ変数を増やすループを入力すると、いくつかのCPU時間が無駄になります。その後、負荷平均を約50%に保つために、遅延ループを調整しながらスレッドのスケジューリング間隔を減らし続けました。
テストの結果、スレッドが50ミリ秒と100ミリ秒で予約されていると、topによって報告された値が正しいことがわかりました。
スケジューリング間隔を10ミリ秒に設定すると、2〜4%の差が現れ始めます。間隔を5msに減らすと、差は12%に増えます。最後に、間隔を2msに減らすと、トップ出力が完全に混乱し、アプリケーションがCPU時間の33%を使用している間、トップに100%アイドル時間が表示されます。
これは、問題が過小サンプリングによって引き起こされたという疑いを確認しているようです。
誰でもこれを確認できますか?カーネルがCPU使用率をどのように測定するかを知っている人はいますか?
ベストアンサー1
表示された数字は推定、ほとんどはサンプリングによって得られます。一般的な概要には良いですが、小数点以下の詳細な管理には役に立ちません。 「CPU使用量」の測定は基本的に役に立たない。システムに過負荷がかかると、100%に近い値が得られます(作業はほとんど行われません)。ワークロードのパフォーマンスに基づいて全体的な目標を定義し、必要に応じて測定および調整します。
CONFIG_HZを増やすと、カーネルのオーバーヘッドが増えます(ただし、対話型応答が良くなる可能性があります)。デフォルトは、「一般的な」ワークロードに対する合理的な妥協点です。他の値がユースケースに適しているという確かな証拠がある場合は、その値を変更してください。