操作系统:多线程减速程序(C)

时间:2014-04-24 02:57:44

标签: c multithreading

我们的想法是编写一个接受大量随机数来创建的程序,然后在用户输入的许多线程之间划分负载,并测量使用多个线程时获得的速度增加。我的问题;但是,我添加的线程越多,我的程序就越慢。不确定有什么问题。到目前为止,这是我的代码片段:

...
    for (i=0; i<numThreads; i++){
        vals *values;
        values = (vals *)malloc(sizeof(vals));
        values->randoms = count;
        values->id = i;
        pthread_create(&tid[i], NULL, run, (void *) values);
    }

    for (i=0; i<numThreads; i++)
        pthread_join(tid[i], NULL);

    timeElapsed = getMilliSeconds() - timeStart;
    printf("Elapsed time:  %lf seconds\n",(double)(timeElapsed/1000.0));

    exit(EXIT_SUCCESS);
}

void *run(void *arg) {
    vals *values;
    long long int i;
    long long int randoms;

    values = (vals*)arg;
    randoms = values->randoms;
    srandom(values->id);

    for (i = 0; i < randoms; i++) {
        random();
    }

    pthread_exit(NULL);
}

vals是一个包含两个int值(randoms和id)的结构。 randoms包含要生成的随机数的数量除以线程数(以划分负载),并且id为每个要用作种子的线程保存唯一的id。我需要创建结构,这样我就可以将多个值传递给线程调用的worker函数。

任何想法为什么它会在更多线程下运行得更慢?

2 个答案:

答案 0 :(得分:2)

多线程程序可能会在多个CPU可用的环境中显示出改进的性能。但是,当缺少可用的CPU资源时,每个线程都必须等待调度CPU时间。 “上下文切换”是指一个线程从CPU切换出来,另一个线程切换进来。“上下文切换”并不是一个无关紧要的任务。

因此,线程越多,等待CPU资源的线程就越多,内核花在上下文切换上的时间就越多(而不是真正的工作)。

答案 1 :(得分:2)

很可能你遇到了false sharing。生成随机数涉及改变某些共享状态,并且多个线程不断修改相同的值有效地消除了从CPU的内存缓存中获得的任何好处。发生的事情是每次线程A想要访问该共享状态时,它必须等待线程B的CPU核心刷新其缓存。任何时候线程B想要访问它,它必须等待线程A的CPU核心刷新其缓存。

从另一个角度来看,单线程程序会执行以下操作:

Load state into CPU cache
for (i = 0 to randoms ...)
    generate random number

有两个线程,每个线程都这样做:

for (i = 0 to randoms ...)
    wait for other CPU core to flush its cache
    generate random number
  

我的问题;但是,我添加的线程越多,我的程序就越慢。

如果你有比CPU内核更多的处理线程,那么你的程序将会变慢。使用两个内核,您可以使用计算绑定操作执行绝对最佳操作,其运行速度是单线程解决方案的两倍。如果你有三个线程,那么在某些时候线程调度程序将不得不停止其中一个线程,以便第三个线程可以获得一些时间。这些上下文切换需要时间 - 在计算绑定操作的上下文中相对大量的时间。通常,您不希望拥有比CPU核心更多的计算绑定线程。

(当然没有超线程。通过超线程,你可以潜在地同时运行四个线程,尽管你甚至不可能获得3倍的改进。)

相关问题