[英]how to avoid overhead of openMP in nested loops
我有两个版本的代码产生相同的结果,我试图只并行化嵌套for
循环的内部循环。 我没有得到太多的加速,但我没想到1对1,因为我只想并行化内循环。
我的主要问题是为什么这两个版本的运行时间相似? 没有第二个版本叉线只有一次,避免在每次迭代开始了新线程的开销i
作为第一个版本?
第一个版本的代码在外部循环的每次迭代中启动线程,如下所示:
for(i=0; i<2000000; i++){
sum = 0;
#pragma omp parallel for private(j) reduction(+:sum)
for(j=0; j<1000; j++){
sum += 1;
}
final += sum;
}
printf("final=%d\n",final/2000000);
使用此输出和运行时:
OMP_NUM_THREADS = 1
final=1000
real 0m5.847s
user 0m5.628s
sys 0m0.212s
OMP_NUM_THREADS = 4
final=1000
real 0m4.017s
user 0m15.612s
sys 0m0.336s
第二个版本的代码在外部循环之前启动一次线程(?)并像这样并行化内部循环:
#pragma omp parallel private(i,j)
for(i=0; i<2000000; i++){
sum = 0;
#pragma omp barrier
#pragma omp for reduction(+:sum)
for(j=0; j<1000; j++){
sum += 1;
}
#pragma omp single
final += sum;
}
printf("final=%d\n",final/2000000);
使用此输出和运行时:
OMP_NUM_THREADS = 1
final=1000
real 0m5.476s
user 0m4.964s
sys 0m0.504s
OMP_NUM_THREADS = 4
final=1000
real 0m4.347s
user 0m15.984s
sys 0m1.204s
为什么第二个版本不比第一个版本快得多? 它不会避免在每次循环迭代时启动线程的开销,还是我做错了什么?
OpenMP实现可以使用线程池来消除在遇到并行构造时启动线程的开销。 为第一个并行构造启动一个OMP_NUM_THREADS
线程池,并在构造完成后将从属线程返回到池中。 当遇到后来的并行构造时,可以重新分配这些空闲线程。
例如,请参阅Sun Studio OpenMP实现中对线程池的此解释。
你似乎正在回顾阿姆达尔定律的步骤:它说的是并行过程与它自己的开销。 Amadhl发现的一件事是,无论你在程序中加入多少并行性,它始终都要以相同的加速速度开始。 当程序需要足够的工作来补偿额外的处理能力时,并行性才开始改善运行时间/性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.