デスクトップには、現在のCPU使用率を示す小さなウィジェットがあります。また、2つのコアのそれぞれの使用法も示しています。
私はいつも疑問に思っていましたが、CPUはどのように処理能力のどれだけが使用されているかを計算しますか?また、CPUが集中的な計算を行ってハングアップした場合、CPU(またはこのアクティビティを処理するもの)は、ハングアップすることなく、どのように使用状況を調べることができますか?
デスクトップには、現在のCPU使用率を示す小さなウィジェットがあります。また、2つのコアのそれぞれの使用法も示しています。
私はいつも疑問に思っていましたが、CPUはどのように処理能力のどれだけが使用されているかを計算しますか?また、CPUが集中的な計算を行ってハングアップした場合、CPU(またはこのアクティビティを処理するもの)は、ハングアップすることなく、どのように使用状況を調べることができますか?
他のタスクを実行できないときに実行されるアイドルタスクと呼ばれる特別なタスクがあります。使用率は、アイドルタスクを実行していない時間の割合です。OSは、アイドルタスクの実行に費やされた時間の現在の合計を保持します。
実行中の合計の2つのサンプルをn秒間隔で取得すると、アイドル状態のタスクの実行に費やされたn秒のパーセンテージを(2番目のサンプル-最初のサンプル)/nとして計算できます。
これはOSが行うことであり、CPUではないことに注意してください。タスクの概念はCPUレベルには存在しません!(実際には、アイドルタスクはプロセッサをHLT命令でスリープ状態にするため、CPUはプロセッサが使用されていないことを認識します)
2番目の質問に関しては、最新のオペレーティングシステムはプリエンプティブにマルチタスクです。つまり、OSはいつでもタスクから切り替えることができます。OSは実際にどのようにしてCPUをタスクから奪いますか?割り込み: http: //en.wikipedia.org/wiki/Interrupt
CPUはそれ自体では使用量の計算を行いません。そのタスクを簡単にするハードウェア機能があるかもしれませんが、それは主にオペレーティングシステムの仕事です。したがって、明らかに実装の詳細は異なります(特にマルチコアシステムの場合)。
一般的な考え方は、CPUが実行する必要のあるキューの長さを確認することです。オペレーティングシステムは、スケジューラを定期的に調べて、実行する必要のある処理の数を決定する場合があります。
これは、Linuxの関数(ウィキペディアからリッピング)で、次の計算を実行します。
#define FSHIFT 11 /* nr of bits of precision */
#define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */
#define LOAD_FREQ (5*HZ) /* 5 sec intervals */
#define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */
#define EXP_5 2014 /* 1/exp(5sec/5min) */
#define EXP_15 2037 /* 1/exp(5sec/15min) */
#define CALC_LOAD(load,exp,n) \
load *= exp; \
load += n*(FIXED_1-exp); \
load >>= FSHIFT;
unsigned long avenrun[3];
static inline void calc_load(unsigned long ticks)
{
unsigned long active_tasks; /* fixed-point */
static int count = LOAD_FREQ;
count -= ticks;
if (count < 0) {
count += LOAD_FREQ;
active_tasks = count_active_tasks();
CALC_LOAD(avenrun[0], EXP_1, active_tasks);
CALC_LOAD(avenrun[1], EXP_5, active_tasks);
CALC_LOAD(avenrun[2], EXP_15, active_tasks);
}
}
質問の2番目の部分については、最新のオペレーティングシステムのほとんどはマルチタスクです。つまり、OSは、プログラムにすべての処理時間を費やさせたり、プログラム自体に何も持たせたりすることはありません(そうさせない限り)。つまり、アプリケーションがハングしているように見えても、OSは自分の作業のためにしばらく時間を奪うことができます。
CPU使用率を取得するには、定期的に合計プロセス時間をサンプリングし、違いを見つけます。
たとえば、これらがプロセス1のCPU時間である場合:
kernel: 1:00:00.0000
user: 9:00:00.0000
そして、2秒後に再びそれらを取得します。それらは次のとおりです。
kernel: 1:00:00.0300
user: 9:00:00.6100
カーネル時間(の差0.03
)とユーザー時間(0.61
)を減算し、それらを合計して(0.64
)、2秒のサンプル時間で除算します(0.32
)。
したがって、過去2秒間で、プロセスは平均32%のCPU時間を使用しました。
この情報を取得するために必要な特定のシステムコールは、プラットフォームごとに(明らかに)異なります。Windowsでは、GetProcessTimes、または使用済みまたはアイドル状態の合計CPU時間へのショートカットが必要な場合はGetSystemTimesを使用できます。
これを行う1つの方法は次のとおりです。
サンプリング間隔を選択します。たとえば、実際の経過時間の5分(300秒)ごとに選択します。これはから取得できますgettimeofday
。
その300秒で使用した処理時間を取得します。times()
呼び出しを使用してこれを取得できます。これはnew_process_time - old_process_time
、old_process_time
最後の時間間隔から節約したプロセス時間です。
CPUのパーセンテージは次のようになり(process_time/elapsed_time)*100.0
ます。これらの計算を行うために、300秒ごとに通知するアラームを設定できます。
特定の目標CPUパーセンテージを超えて使用したくないプロセスがあります。この方法はかなりうまく機能し、私のシステムモニターとよく一致します。CPUを使いすぎると、少しの間眠ります。
あなたがそれをすることができるいくつかの方法があります:
プロセッサは、パフォーマンスを測定するいくつかのカウンタを維持しています。Papiインターフェイスを使用してそれらにアクセスできます。たとえば、ここに簡単な紹介があります:http: //blogs.oracle.com/jonh/entry/performance_counter_generic_events
また:http ://www.drdobbs.com/tools/184406109
必要なカウンターは、ビジーサイクルの数であるPAPI_TOT_CYCです(私が正しく覚えている場合)
これは、同様のコードに少し触れることからの私の基本的な理解です。タスクマネージャーなどのプログラムやウィジェットアクセスシステムはNtQuerySystemInformation()などを呼び出し、OSから収集した情報を使用して、CPUがアイドル状態または使用されている時間(標準時間)の割合を簡単に計算します。CPUはアイドル状態を認識しているため、アイドル状態でないときを判断できます。これらのプログラムは確かに詰まる可能性があります...私の不器用なラップトップのタスクマネージャーは、CPU使用率を計算するときに、100%でいっぱいになると常にフリーズします。
一連の命令のCPU使用率を計算するための関数呼び出しを示すサンプルコードのクールなビットがMSDNWebサイトにあります:http://msdn.microsoft.com/en-us/library/aa364157(VS.85).aspx
これらのシステムコールが行うことは、私が信じているカーネルコードにアクセスすることです...これは私の理解の範囲を超えています。
まあ、私が理解している限り、巨人がいます
while(true){}
オペレーティングシステムがスピンアップするループ。プロセスはそのループ内から管理されます。これにより、外部コードをプロセッサ上でチャンクで直接実行できます。誇張しすぎることなく、これは実際に起こっていることを非常に単純化したものです。
CPUは「ハングアップ」せず、単にピーク容量で動作しています。つまり、毎秒物理的に可能な数の命令を処理しています。CPU使用率を計算しているプロセスは、それらの命令の一部です。アプリケーションがCPUの能力よりも速く操作を行おうとすると、単に遅延するため、「ハングアップ」します。
CPU使用率の計算は、使用可能な合計使用率に基づいています。したがって、CPUに2つのコアがあり、一方のコアの使用率が30%で、もう一方のコアの使用率が60%の場合、全体の使用率は45%になります。また、個々のコアの使用法を確認することもできます。