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

时间:2012-11-23 15:08:43

标签: c multithreading unix

我正在编写一个使用一定比例CPU的小程序。基本策略是我将不断检查CPU使用情况,并在使用级别高于给定值时使进程休眠。

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

问题是我不断获得CPU的高使用率,即使我给出一个小值作为参数。经过多次实验,它似乎是由多线程共享字段引起的。

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

(代码2)最初我认为是shell命令使用率非常高,所以我在run()中评论了无限循环,只留下getCpuUsage()运行。但是,CPU使用率几乎为零。

(代码3)然后,我编写了另一个独立于cpuUsage的run()函数,该函数用于使用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);
    }
}

2 个答案:

答案 0 :(得分:2)

  

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

是的,通过多个CPU上的多个线程对共享内存位置进行常量读/写操作会导致高速缓存行在CPU之间不断移动(高速缓存反弹)。 IMO,这是天真“并行”应用程序中可扩展性差的最重要原因。

答案 1 :(得分:1)

确定。 Code1创建了一个尽可能快的线程 - 一个popen。所以这个线程耗尽了所有的cpu-time。另一个线程(主线程)做了睡眠,但不是popening线程...

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

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

所以基本上你应该做什么(如果你真的想为此目的使用top),你调用它,然后睡觉让我们说1秒或100ms,并且看看你的主循环在code1中调整。

while (1) {
    usleep (100*1000);
    out = popen(CPU_COMMAND, "r");