3

我有这个 C++ 代码。

循环遍历矩阵,找到每一行中的最小元素,然后从对应行的每个元素中减去它。变量 myr 是所有最小元素的总和

尝试并行:

int min = 0;
int myr = 0;  
int temp[SIZE][SIZE];
int size = 0;
...//some initialization

omp_set_num_threads(1);
start_time = omp_get_wtime();
    #ifdef _OPENMP
    #pragma omp parallel for firstprivate(min, size) reduction(+:myr) 
    #endif
    for(int i = 0; i < size; i++){
        min = INFINITY;
        for(int j = 0; j < size; j++){
                if (temp[i][j] < min)                
                    min = temp[i][j];                        
        }
        myr+=min;
        for(int j = 0; j < size; j++) 
                temp[i][j]-=min;
    }
end_time = omp_get_wtime();

如果我设置omp_set_num_threads(2);这部分代码开始工作得更慢。

我的 proc 有 2 个核心

为什么代码在 2 个线程上运行速度较慢?

4

2 回答 2

3

一定有一些混叠或正在发生的事情。让 OpenMP 变得更简单:

int const size0 = size;
#ifdef _OPENMP
#pragma omp parallel for reduction(+:myr) 
#endif
for(int i = 0; i < size0; i++){
    int min = INFINITY;
    int * tmp = temp[i];
    for(int j = 0; j < size0; j++){
            if (tmp[j] < min)                
                min = tmp[j];                        
    }
    for(int j = 0; j < size0; j++) 
            tmp[j]-=min;
    myr+=min;
}

也就是说,const如果可以的话,将大多数变量放在本地。

于 2012-09-10T13:36:53.850 回答
0

并行部分可以重新解释如下(我使用了@jens-gustedt 的片段,但根据我的经验,它并没有太大区别):

#pragma omp parallel private(myr_private) shared(myr)
{
    myr_private = 0;
    #pragma omp for 
    for(int i = 0; i < size; i++){
        int min = INFINITY;
        int * tmp = temp[i];
        for(int j = 0; j < size; j++){
            if (tmp[j] < min)                
                min = tmp[j];                        
        }
        for(int j = 0; j < size; j++) 
            tmp[j]-=min;
        myr_private+=min;
    }
    #pragma omp critical
    {
        myr+=myr_private;
    }
}

(此解释直接来自http://www.openmp.org/mp-documents/OpenMP3.1.pdf示例 A.36.2c)。如果线程数 n>1,则在#pragma omp parallel创建额外线程时会产生开销,然后在临界区中创建所有线程都应等待的开销。

我尝试了不同的矩阵大小,在我有限的测试中,两个线程在大小超过 1000 时要快得多,而在大小低于 500 时开始落后。

于 2012-09-11T18:54:21.440 回答