OpenMP:哪些示例可以获得更好的性能提升?

时间:2011-07-24 17:10:21

标签: performance openmp parallel-processing

哪一个可以获得更好的表现?

示例1

 #pragma omp parallel for private (i,j)
    for(i = 0; i < 100; i++) {
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

示例2

   for(i = 0; i < 100; i++) {
        #pragma omp parallel for private (i,j)
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

跟进问题使用示例3是否有效?

 #pragma omp parallel for private (i)
   for(i = 0; i < 100; i++) {
        #pragma omp parallel for private (j)
        for (j=0; j< 100; j++){
           ....do sth...
        }
    }

2 个答案:

答案 0 :(得分:2)

通常,示例1是最好的,因为它并行化最外层循环,这最小化了线程分叉/连接开销。尽管许多OpenMP实现预先分配了线程池,但是仍然存在将逻辑任务分派给工作线程(也就是一个线程团队)并加入它们的开销。另请注意,当您使用动态调度(例如schedule(dynamic, 1))时,此任务调度开销将会出现问题。

因此,示例2可能会产生显着的并行开销,尤其是当for-i的行程计数很大(但100可以)时,for-j的工作量很小。 可能是一个含糊不清的术语,取决于许多变量。但是,使用OpenMP不到1毫秒肯定是浪费。

但是,如果for-i不可并行化且只有for-j可并行化,则Example2是唯一的选项。在这种情况下,您必须仔细考虑并行工作负载量是否可以抵消并行开销。

一旦for-ifor-j可安全地并行化(即,分别在每两个循环中没有循环携带的流依赖性),示例3是完全有效的。 Example3称为嵌套并行。你可以看看this article。应谨慎使用嵌套并行性。在许多OpenMP实现中,您需要通过调用omp_set_nested来手动打开嵌套并行性。但是,由于嵌套并行性可能会产生大量线程,因此其优势可能会大大降低。

答案 1 :(得分:1)

这取决于你在内循环中的数量。如果它很小,那么激活太多线程将代表开销。如果工作量很大,我可能会考虑选项2,具体取决于您的机器的核心数量。

BTW,在示例1中,唯一需要将变量标记为私有的地方是“j”。在所有其他情况下,它是隐式的。