哪一个可以获得更好的表现?
示例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...
}
}
答案 0 :(得分:2)
通常,示例1是最好的,因为它并行化最外层循环,这最小化了线程分叉/连接开销。尽管许多OpenMP实现预先分配了线程池,但是仍然存在将逻辑任务分派给工作线程(也就是一个线程团队)并加入它们的开销。另请注意,当您使用动态调度(例如schedule(dynamic, 1)
)时,此任务调度开销将会出现问题。
因此,示例2可能会产生显着的并行开销,尤其是当for-i
的行程计数很大(但100可以)时,for-j
的工作量很小。 小可能是一个含糊不清的术语,取决于许多变量。但是,使用OpenMP不到1毫秒肯定是浪费。
但是,如果for-i
不可并行化且只有for-j
可并行化,则Example2是唯一的选项。在这种情况下,您必须仔细考虑并行工作负载量是否可以抵消并行开销。
一旦for-i
和for-j
可安全地并行化(即,分别在每两个循环中没有循环携带的流依赖性),示例3是完全有效的。 Example3称为嵌套并行。你可以看看this article。应谨慎使用嵌套并行性。在许多OpenMP实现中,您需要通过调用omp_set_nested
来手动打开嵌套并行性。但是,由于嵌套并行性可能会产生大量线程,因此其优势可能会大大降低。
答案 1 :(得分:1)
这取决于你在内循环中的数量。如果它很小,那么激活太多线程将代表开销。如果工作量很大,我可能会考虑选项2,具体取决于您的机器的核心数量。
BTW,在示例1中,唯一需要将变量标记为私有的地方是“j”。在所有其他情况下,它是隐式的。