1

我正在编写一个使用一定比例 CPU 的小程序。基本策略是我会不断检查 CPU 使用率,如果使用率高于给定值,则让进程休眠。

此外,由于我使用的是 MacOS(没有像 Linux 那样的 proc/stat,C# 中没有 PerformanceCounter),我必须top在另一个线程中执行命令并从中获取 CPU 使用率。

问题是即使我给出了一个很小的值作为参数,我的 CPU 使用率也一直很高。并且经过多次实验,似乎是由多线程共享字段引起的。

这是我的代码(代码 1)和实验:

(代码2)一开始我以为是shell命令使用率很高,所以在里面注释掉了无限循环run(),只留下getCpuUsage()运行。但是,CPU 使用率几乎为零。

(代码3)然后,我又写了一个run()独立于cpuUsage的函数,打算使用50%的CPU。它运作良好!我认为代码 1 和代码 3 之间的唯一区别是cpuUsage. 所以我想知道线程之间的共享字段是否会大量使用CPU?

代码 1

const char CPU_COMMAND[] = "top -stats cpu -l 1 -n 0| grep CPU\\ usage | cut -c 12-15";

int cpuUsage; // shared field that stores the cpu usage

// thread that continuously check CPU usage
// and store it in cpuUsage
void getCpuUsage() {
    char usage[3];
    FILE *out;
    while (1) {
        out = popen(CPU_COMMAND, "r");
        if (fgets(usage, 3, out) != NULL) {
            cpuUsage = atof(usage);
        } else {
            cpuUsage = 0;
        }
        pclose(out);
    }
}

// keep the CPU usage under ratio
void run(int ratio) {
    pthread_t id;
    int ret = pthread_create(&id, NULL, (void *)getCpuUsage, NULL);
    if (ret!=0) printf("thread error!");

    while (1) {
        // if current cpu usage is higher than ration, make it asleep
        if (cpuUsage > ratio) {
            usleep(10);
        }
    }

    pthread_join(id, NULL);
}

代码 2

// keep the CPU usage under ratio
void run(int ratio) {
    pthread_t id;
    int ret = pthread_create(&id, NULL, (void *)getCpuUsage, NULL);
    if (ret!=0) printf("thread error!");

    /*while (1) {
        // if current cpu usage is higher than ration, make it asleep
        if (cpuUsage > ratio) {
            usleep(10);
        }
    }*/

    pthread_join(id, NULL);
}

代码 3

void run() {
    const clock_t busyTime = 10;
    const clock_t idleTime = busyTime;

    while (1) {
        clock_t startTime = clock();
        while (clock() - startTime <= busyTime);
        usleep(idleTime);
    }
}
4

2 回答 2

2

多线程C程序中的共享字段是否大量使用CPU?

是的,多个 CPU 上的多个线程对共享内存位置的持续读取/写入会导致缓存线在 CPU 之间不断移动(缓存反弹)。IMO,这是幼稚的“并行”应用程序可扩展性差的最重要原因。

于 2012-11-23T15:22:13.367 回答
1

好的。Code1 创建了一个线程,该线程尽可能快地执行 popen。所以这个线程用完了所有的cpu时间。另一个线程(主线程)确实在睡觉,但不是正在弹出的线程......

Code2 还启动这个使用 cpu 的线程,然后等待它完成(加入),这永远不会发生。

Code3 运行一段时间,然后休眠相同的时间,所以它应该用完大约 50%。

所以基本上你应该做什么(如果你真的想使用 top 来达到这个目的),你调用它,然后休眠让我们说 1 秒或 100 毫秒,看看你在 code1 中的主循环是否调整。

while (1) {
    usleep (100*1000);
    out = popen(CPU_COMMAND, "r");
于 2012-11-23T15:23:08.073 回答