負荷は非常に不正な数です。塩の粒でそれを取る。
非常に速く連続して多くのタスクを大量に生成する場合、実行キュー内のプロセスの数は、それらの負荷を登録するには小さすぎます(カーネルは5秒ごとに負荷をカウントします)。
この例を考えてみましょう。8個の論理コアを持つホストで、このPythonスクリプトは大きなCPU使用率(約85%)を登録しますが、負荷はほとんどありません。
import os, sys
while True:
for j in range(8):
parent = os.fork()
if not parent:
n = 0
for i in range(10000):
n += 1
sys.exit(0)
for j in range(8):
os.wait()
別の実装、これwait
は8のグループで回避します(これはテストをゆがめるでしょう)。ここでは、親は常に、アクティブなCPUの数で子の数を維持しようとします。そのため、最初の方法よりもずっと忙しくなり、できればより正確になります。
/* Compile with flags -O0 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define ITERATIONS 50000
int maxchild = 0;
volatile int numspawned = 0;
void childhandle(
int signal)
{
int stat;
/* Handle all exited children, until none are left to handle */
while (waitpid(-1, &stat, WNOHANG) > 0) {
numspawned--;
}
}
/* Stupid task for our children to do */
void do_task(
void)
{
int i,j;
for (i=0; i < ITERATIONS; i++)
j++;
exit(0);
}
int main() {
pid_t pid;
struct sigaction act;
sigset_t sigs, old;
maxchild = sysconf(_SC_NPROCESSORS_ONLN);
/* Setup child handler */
memset(&act, 0, sizeof(act));
act.sa_handler = childhandle;
if (sigaction(SIGCHLD, &act, NULL) < 0)
err(EXIT_FAILURE, "sigaction");
/* Defer the sigchild signal */
sigemptyset(&sigs);
sigaddset(&sigs, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &sigs, &old) < 0)
err(EXIT_FAILURE, "sigprocmask");
/* Create processes, where our maxchild value is not met */
while (1) {
while (numspawned < maxchild) {
pid = fork();
if (pid < 0)
err(EXIT_FAILURE, "fork");
else if (pid == 0) /* child process */
do_task();
else /* parent */
numspawned++;
}
/* Atomically unblocks signal, handler then picks it up, reblocks on finish */
if (sigsuspend(&old) < 0 && errno != EINTR)
err(EXIT_FAILURE, "sigsuspend");
}
}
この動作の理由は、アルゴリズムが実際のタスク(10000までカウント)を実行するよりも多くの時間を子プロセスの作成に費やしているためです。まだ作成されていないタスクは「実行可能」状態にカウントできませんが、生成されるとCPU時間で%sysを占有します。
そのため、実際に行われている作業が、多数のタスク(スレッド、またはプロセス)を多数連続して生成するという答えが返される可能性があります。