openMp改写的程序比串行还慢

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了openMp改写的程序比串行还慢相关的知识,希望对你有一定的参考价值。

最近刚刚接触OpenMp,写了简单的程序, 发现在4核4线程运行的时间比4核单线程的时候还要多,不知道为什么,希望有人能帮助我发现一下问题。代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <omp.h>

#define length 100

int main(void)

unsigned int seed = (unsigned)time(NULL);
int i,j;
float min,max,avg,sum;
max = avg = sum = 0.0;
min = 10.0;

float A[length], B[length], C[length];

#pragma omp parallel for
for(i=0; i<length; i++)

A[i] = (rand_r(&seed))%10;
B[i] = (rand_r(&seed))%10;


#pragma omp parallel for
for(i=0; i<length; i++)

C[i] = (A[i]+B[i])/2;


#pragma omp parallel for reduction(+:sum) shared(max,min)
for(i=0; i<length; i++)

#pragma omp critical

if(C[i]>max) max = C[i];
if(C[i]<min) min = C[i];

sum += A[i];


avg = sum/length;
printf("The average of array is %f\n", avg);
printf("The smallest element of array is %f\n", min);
printf("The largest element of array is %f\n", max);

return 0;



希望有人能帮忙发现一下问题,现在结果运行正确,而且确实是多线程再跑,可是速度比单线程慢好多。谢谢。
晕,那个sum求和是sum+=C[i];另外我想问一下这个并行的部分存在冲突么?

参考技术A 运行的慢是因为你的length太小。并行的话比串行需要时间去分,还需要时间再合。所以当你数据量太小时反而用串行的就比较快了。
你换成一亿就能看出差距了。
我没看出来哪有冲突。但是我觉得你上面赋值和算c那这么写也许效率更快。
#pragma omp parallel for
for(i=0; i<length; i++)

A[i] = (rand_r(&seed))%10;
B[i] = (rand_r(&seed))%10;
C[i] = (A[i]+B[i])/2;

还有,你根本没用到头文件time.h啊。你写这个头文件干嘛?是不是想看运行时间啊。追问

嗯,对,我是感觉可能计算量太小了,不过我试着把计算量增大,并且稍微修改了一下,发现加速比还是不好。那个time.h头文件,我之前确实是用来算时间的,后来我用了multi2sim来运行,直接看cycles了,忘记去掉了。。。另外我试着把程序又做了修改,把critical那部分修改了一下,用数组来记录每个线程单独的min和max,最后再把几个线程的min和max进行比较,得到最终结果,实现并行,不过感觉效果还是一般。不知道是怎么回事。

追答

这个时间提高多少呢?如果基本没变,你就要看看你是否用到了openmp.h了,因为就算没成功引用到这个头文件,编译器也会把相应的paralle语句忽略而运行的。

追问

用到了omp.h,因为用了数组来分存每个线程的max和min,用到了omp_get_thread_num().用windows api测试的结果加速比是2(4线程的情况下)。但是用multi2sim在linux下面结果就很悲催。


这两个图Contexts是线程数目,这里的时间不是真正意义的运行时间,有价值的是cycles,可以cycles还是增多了,很无语。。。

追答

把你改后的代码贴出来让我看看吧。cycles是啥啊?

追问

长度抄了。。只能传个截图了,不好意思。。程序如下:

cycles我觉得就是cpu执行了多少个周期吧。可以简单地看成与真实的运行时间相对应。加速比是4的话,cycles应该会变成原来的四分之一。

追答

这个不知道了。我觉得你的代码没有什么问题。
1.但是你看,你顺序执行时instructions 是65989,并行时instructions 是284256.也就是说你并行时居然执行的命令大概是顺序执行时的四倍。正常来说的话不应该是1:1的么?
2.你顺序执行时instructionsPerSecond是113341,并行时是265496,所以说你并行时执行的速度比顺序执行时快两倍多。

我觉得根据上面的2和contxt来说,你确实是并行了。
但是根据1,虽然你的东西并行运算了,但是每次并行都是把1:length都执行了一遍,而不是分成Num_thread个来实现的。

以上只是我的分析,我不确定对不对,因为我总觉得你的代码没有问题。

刚才又想到个问题。你看把运行时间看成和circles成正比了是吧。这个应该是不对的。你看,一共有三个值:cycles per second,cycles,和instructions per cycle。 这一个数和第三个数的乘积应该就是instructionsPerSecond。执行速度应该是和Instructions per second成正比的。所以时间应该是和Instructions per second成反比的(当instructions相同的时候),但是因为你的instructions不一样多,所以比时间就不对了,还是应该比运行速度,也就是Instructions per second。很明显,你并行时运行时的速度比顺序的快很多。但因为并行时你运行了更多的Instructions,所以,并行用的时间却比顺序执行时长。

综上所诉,我觉得最有可能的就是你的i被程序当成是private的了。你尝试把他们定义为公有的试试。

本回答被提问者采纳

以上是关于openMp改写的程序比串行还慢的主要内容,如果未能解决你的问题,请参考以下文章

OpenMP 循环运行代码比串行循环慢

为啥我使用 openMP atomic 的并行代码比串行代码花费更长的时间?

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

OpenMP 并行代码与串行代码的输出不同

Linux 上的多核计算性能低下(openMP、boost::thread 等)

内部的openmp延迟