高分求助!!!!openMP并行效率问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高分求助!!!!openMP并行效率问题相关的知识,希望对你有一定的参考价值。

试了几个基本的例子程序,都没有并行效率,比如:

PROGRAM parallel_01
USE omp_lib
IMPLICIT NONE

INTEGER :: i,j,ii
INTEGER(4) :: time_begin, time_end, time_rate
REAL, DIMENSION(1:5000,1:5000) :: f, g
REAL :: k

CALL system_clock(time_begin,time_rate)
CALL omp_set_num_threads(4)

k = 0 ! 重新初始化k的值
CALL system_clock(time_begin,time_rate)
do ii=1,100 !这个循环纯粹为了增加计算时间,更容易显示并行效率
!$omp parallel private(k,j,i)
!$omp do
DO i = 1, 5000
DO j = 1, 5000
f(i,j) = i*j
k = k + 1
END DO
END DO
!$omp end do

!$omp do
DO i = 1, 5000
DO j = 1, 5000
g(i,j) = i*j
k = k + 1
END DO
END DO
!$omp end do
!$omp end parallel
enddo

CALL system_clock(time_end,time_rate)
WRITE(*,*) 'The time wasted on the parallel computing is: ',(time_end - time_begin)/time_rate

END PROGRAM
调用2,3,4核,计算时间基本一样,没有并行效率,这是为啥啊????

参考技术A 时间太短,体现不出来

影响 OpenMP 并行效率的方面

【中文标题】影响 OpenMP 并行效率的方面【英文标题】:Aspects that affects the efficiency of OpenMP parallelism 【发布时间】:2021-07-24 15:52:16 【问题描述】:

我想使用 OpenMP 并行一个大循环以提高其效率。这是玩具代码的主要部分:

vector<int> config;
config.resize(indices.size());

omp_set_num_threads(2);
#pragma omp parallel for schedule(static, 5000) firstprivate(config)
    for (int i = 0; i < 10000; ++i)  // the outer loop that I would like to parallel
#pragma omp simd
        for (int j = 0; j < indices.size(); ++j)  // pick some columns from a big ref_table
            config[j] = ref_table[i][indices[j]];
        
        int index = GetIndex(config); // do simple computations on the picked values to get the index
#pragma omp atomic
        result[index]++;
    

然后我发现如果我使用 2、4 或 8 个线程,我无法提高效率。并行版本的执行时间通常大于顺序版本。外部循环有 10000 次迭代,它们是独立的,所以我希望多个线程并行执行这些迭代。

我猜性能下降的原因可能包括:config 的私​​有副本?或者,ref_table 的随机访问?或者,昂贵的原子操作?那么性能下降的确切原因是什么?更重要的是,我怎样才能获得更短的执行时间?

【问题讨论】:

GetIndex 是做什么的?任何显式或隐藏的内存分配(例如使用向量或列表)? indices.size() 有多大? "or, random access of ref_table?" 多个线程访问同一个内存位置不是问题,只要这些访问是严格只读的。只有至少有一个线程在该位置执行写操作时才会成为问题。 我认为,像往常一样,您的代码受内存限制。这意味着您的程序的速度主要取决于内存读/写的速度。请阅读此答案,我认为它也可能适用于您的情况:***.com/questions/68503586/… 我不认为 #pragma omp simd 应该提供任何加速,即使 indices 更大,因为您正在内部循环中进行收集操作,我无法想象从矢量化中获利。 【参考方案1】:

config 的私有副本或ref_tables 的随机访问都没有问题,我认为工作量非常小,有两个潜在的问题阻碍了高效并行化:

    原子操作太昂贵了。 开销大于工作负载(这只是意味着不值得与 OpenMP 并行化)

我不知道在您的情况下哪个更重要,因此值得尝试摆脱原子操作。有两种情况:

a) 如果results 数组初始化为零,您必须使用:

#pragma omp parallel for reduction(+:result[0:N]) schedule(static, 5000) firstprivate(config) 其中Nresult 数组的大小并删除#pragma omp atomic。请注意,这适用于 OpenMP 4.5 或更高版本。对于 2-10 次迭代的循环,删除 #parama omp simd 也是值得的。因此,您的代码应如下所示:

#pragma omp parallel for reduction(+:result[0:N]) schedule(static, 5000) firstprivate(config)
    for (int i = 0; i < 10000; ++i)  // the outer loop that I would like to parallel
        for (int j = 0; j < indices.size(); ++j)  // pick some columns from a big ref_table
            config[j] = ref_table[i][indices[j]];
        
        int index = GetIndex(config); // do simple computations on the picked values to get the index
        result[index]++;
    

b) 如果result 数组未初始化为零,则解决方案非常相似,但在循环中使用一个临时的零初始化数组,然后将其添加到result 数组中。

如果速度不会提高,那么您的代码不值得在硬件上与 OpenMP 并行化。

【讨论】:

以上是关于高分求助!!!!openMP并行效率问题的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP的主要功能,基本构成体都有哪些

在 OpenMP 并行代码中,memset 并行运行有啥好处吗?

OpenMP 并行用于 - 多个并行用于的 Vs。一个并行,其中包含多个 for

openMP 嵌套并行 for 循环与内部并行 for

OpenMP:嵌套并行化有啥好处?

openMP 没有并行线程