1

我正在尝试使用 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;
}

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

4

2 回答 2

5

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

于 2013-06-19T15:25:31.727 回答
1

tmp您的代码在和中具有竞争条件m。我不知道您真正想要做什么,但此链接可能会有所帮助在不使用关键部分的情况下与 OpenMP 并行填充直方图(数组缩减)

我试着清理你的代码。此代码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
于 2013-06-19T17:06:48.250 回答