只有在将数组设为私有后才能实现多线程加速

时间:2013-06-19 14:45:15

标签: c multithreading openmp

我正在尝试使用openmp学习多线程编程。

首先,我正在测试一个带有大量数组访问操作的嵌套循环,然后将其并行化。我附上下面的代码。基本上,我在内部循环中有这个相当大的数组tmp,如果我让它共享以便每个线程都可以访问和更改它,我的代码实际上会随着线程数量的增加而减慢。我写了它,以便每个线程将完全相同的值写入数组tmp。当我将tmp设为私有时,我的速度与线程数成正比。没有。在这两种情况下,我认为操作完全相同。为什么在共享tmp时速度会变慢?是因为不同的线程试图同时访问同一个地址吗?

int main(){
    int k,m,n,dummy_cntr=5000,nthread=10,id;
    long num=10000000;
    double x[num],tmp[dummy_cntr];
    double tm,fact;
    clock_t st,fn;

    st=clock();
    omp_set_num_threads(nthread);
#pragma omp parallel private(tmp)
    {
        id = omp_get_thread_num();
        printf("Thread no. %d \n",id);
#pragma omp for
        for (k=0; k<num; k++){
            x[k]=k+1;
            for (m=0; m<dummy_cntr; m++){
                tmp[m] = m;
            }
        }
    }
    fn=clock();
    tm=(fn-st)/CLOCKS_PER_SEC;
}

P.S。:我知道在这里使用clock()并没有真正给出正确的时间。我必须将它除以否。在这种情况下,线程获得“time ./a.out”给出的类似输出。

2 个答案:

答案 0 :(得分:5)

这可能是由于缓存争用:如果数组的一部分被两个或更多线程访问,它将被缓存多次,每个核心一个副本:当一个核心需要访问时它,如果数据已被更改,则需要从另一个核心缓存中获取最新版本,这需要一些时间。

答案 1 :(得分:1)

您的代码在tmpm中有竞争条件。我不知道你真正想做什么,但这个链接可能会有所帮助Fill histograms (array reduction) in parallel with OpenMP without using a critical section

我尝试清理你的代码。此代码为每个线程分配tmp的内存,以解决tmp中的错误共享问题。

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

int main() {
    int k,m,dummy_cntr=5000;
    long num=10000000;
    double *x, *tmp;
    double dtime;

    x = (double*)malloc(sizeof(double)*num);

    dtime = omp_get_wtime();
    #pragma omp parallel private(tmp, k)
    {
        tmp = (double*)malloc(sizeof(double)*dummy_cntr);
        #pragma omp for
        for (k=0; k<num; k++){
            x[k]=k+1;
            for (m=0; m<dummy_cntr; m++){
                tmp[m] = m;
            }
        }
        free(tmp);
    }
    dtime = omp_get_wtime() - dtime;
    printf("%f\n", dtime);
    free(x);
    return 0;
}

编译

gcc -fopenmp -O3 -std=c89 -Wall -pedantic foo.c