openmp:线程数的增加会降低性能

Posted

技术标签:

【中文标题】openmp:线程数的增加会降低性能【英文标题】:openmp: increasing of threads number decreases perfomance 【发布时间】:2012-09-10 13:16:04 【问题描述】:

我有这个 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 个线程的代码运行速度较慢?

【问题讨论】:

首先,OMP 并不意味着您会自动提高速度。第二件事,可能条件分支充当了障碍,因此开销更大。 终极问题是:你的算法适合数据并行吗?线程 A 可以运行您的外部 for 循环的迭代,而线程 B 可以运行外部循环的另一个迭代,而不必相互等待吗? 乍一看,它不能。所以你添加一个线程是徒劳的。 @Tony The Lion:为什么你说它不能?它们唯一发生冲突的部分是归约变量,这是最后完成的一个加法。 我看到很多关于多线程标签的问题,人们只是假设更多的线程等于更好的性能。也许我们应该创建一个 wiki 或其他东西来解释为什么并非总是如此。 【参考方案1】:

一定有一些混叠或发生了什么。让 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;

也就是说,如果可以的话,将大部分变量设置为 local 和 const

【讨论】:

【参考方案2】:

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

#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 时开始落后。

【讨论】:

以上是关于openmp:线程数的增加会降低性能的主要内容,如果未能解决你的问题,请参考以下文章

执行时间取决于使用 OpenMP 库增加的线程数?

增加线程数减少时间

多个 OpenMP 线程读取(不写入)共享变量的性能成本?

如何修复 OpenMP 程序的 gdb 运行中的线程数

openMP:并行运行所有线程会导致内存不足异常

单核CPU使用openmp,会大幅度提高计算性能吗?