此代码不会使代码更快地计算4个和.相反,它甚至需要更多时间.此外输出不是预期的.
#include <stdio.h>
#include <omp.h>
int main()
{
int i,j,k,l;
int sum = 0,sum1 = 0,sum2 = 0,sum3 = 0;
#pragma omp parallel
{
#pragma omp sections
{
#pragma omp section
{
printf("%d",omp_get_thread_num());
for(i = 0; i < 500000000; i++) sum = sum + 1;
}
#pragma omp section
{
printf("%d",omp_get_thread_num());
for(i = 0; i < 500000000; i++) sum1 = sum1 + 1;
}
#pragma omp section
{
printf("%d",omp_get_thread_num());
for(i = 0; i < 500000000; i++) sum2 = sum2 + 1;
}
#pragma omp section
{
printf("%d",omp_get_thread_num());
for(i = 0; i < 500000000; i++) sum3 = sum3 + 1;
}
}
}
printf("sum is %d %d %d %d", sum,sum1,sum2,sum3);
}
Run Code Online (Sandbox Code Playgroud)
输出是 sum is 218748707 222052401 239009041 196849489
请告诉我在这里使用openmp的缺陷.
减速来源于这样的事实即sum,sum1,sum2和sum3被共享的变量,因此,编译器必须产生取/更新/存储指令对每个增量,而不是仅仅保持在寄存器中的中间和作为为串行版本的情况.
你应该将每个和使用它所使用的线程本地.最简单的方法是减少每个总和:
#pragma omp parallel private(i) reduction(+:sum,sum1,sum2,sum3)
{
// Rest of the code goes unchanged
}
Run Code Online (Sandbox Code Playgroud)
private(i)将解决问题的结果不正确.reduction(+:sum,sum1,sum2,sum3)将使每个线程累积自己的sum,和的副本sum1,sum2并sum3最终将本地副本添加起来以形成最终值.
以下是一些表现数据:
串行版 - 3.812秒:
$ gcc -o mp.x mp.c -lgomp
$ time ./mp.x
0000sum is 500000000 500000000 500000000 500000000
./mp.x 3.81s user 0.00s system 99% cpu 3.812 total
Run Code Online (Sandbox Code Playgroud)
具有共享变量的OpenMP版本 - 7.982秒:
$ gcc -fopenmp -o mp.x mp.c
$ time OMP_NUM_THREADS=4 ./mp.x
0132sum is 500000000 500000000 500000000 500000000
OMP_NUM_THREADS=4 ./mp.x 21.88s user 0.86s system 284% cpu 7.982 total
Run Code Online (Sandbox Code Playgroud)
OpenMP版本减少 - 1.226秒:
$ gcc -fopenmp -o mp.x mp.c
$ time OMP_NUM_THREADS=4 ./mp.x
0321sum is 500000000 500000000 500000000 500000000
OMP_NUM_THREADS=4 ./mp.x 4.53s user 0.00s system 370% cpu 1.226 total
Run Code Online (Sandbox Code Playgroud)
还存在另外会减慢速度另一个代码转换,这是一个事实,即sum,sum1,sum2和sum3位于主程序的堆叠上,而部分代码正在由OpenMP的处理器中提取并投入单独的函数,然后由称为并行团队中的每个线程.该函数提供了一个数据结构,其中包含指向四个共享和的指针,并且代码与这些指针一起操作.您可以在两种情况下比较汇编器输出并亲自查看 - 如果您想深入了解并行性能,那么这样做非常有益.