为什么我的OpenMP c++代码比串行代码慢
why my OpenMP C++ code is slower than a serial code?
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>
using namespace std;
void output(float a[], float X[], float Y[], int I, int J)
{
ofstream ft;
int i;
ft.open("flow.dat");
ft<<"variables="x","y","a""<<"n"
<<"zone f=point"<<"n"
<<"I="<<I<<",J="<<J<<"n"
<<endl;
for(int i=0;i<I*J;i++)
{
ft<<setiosflags(ios::scientific)
<<X[i]<<" "<<Y[i]<<" "<<a[i]<<endl;
}
ft.close();
}
void set(float a[], float X[], float Y[], int I, int J, float hx, float hy)
{
for(int j=0;j<J;j++)
for(int i=0;i<I;i++)
{
int iC=j*I+i;
X[iC]=i*hx;
Y[iC]=j*hy;
a[iC]=0.0;
if(j==J-1) a[iC]=1.0;
}
}
void difference_serial(float a[], int I, int J, const float hx, const float hy)
{
const float aC=(hx*hx+hy*hy)*2;
const float aX=hy*hy;
const float aY=hx*hx;
for(int j=1;j<J-1;j++)
for(int i=1;i<I-1;i++)
{
int iC=j*I+i;
int iL=iC-1;
int iR=iC+1;
int iU=iC+I;
int iD=iC-I;
a[iC]=(aX*(a[iL]+a[iR])+aY*(a[iU]+a[iD]))/aC;
}
}
void difference_omp(float a[], int I, int J, const float hx, const float hy)
{
const float aC=(hx*hx+hy*hy)*2;
const float aX=hy*hy;
const float aY=hx*hx;
int i,j,iC,iL,iR,iU,iD;
#pragma omp parallel for private(i,j,iC,iL,iR,iU,iD) shared(a,I,J) schedule(dynamic)
for( j=1;j<J-1;j++)
for( i=1;i<I-1;i++)
{
iC=j*I+i;
iL=iC-1;
iR=iC+1;
iU=iC+I;
iD=iC-I;
a[iC]=(aX*(a[iL]+a[iR])+aY*(a[iU]+a[iD]))/aC;
}
}
int main()
{
const int I=129;
const int J=129;
const int N=I*J;
const float hx=1.0/(I-1);
const float hy=1.0/(J-1);
float *a=new float[N];
float *X=new float[N];
float *Y=new float[N];
//set the grid and flow
set(a,X,Y,I,J,hx,hy);
//iteation
clock_t start=clock();
for(int it=0;it<10000;it++)
difference_serial(a,I,J,hx,hy);
clock_t end=clock();
printf("Serial time=%fn",(float)(end-start)/CLOCKS_PER_SEC);
set(a,X,Y,I,J,hx,hy);
clock_t start2=clock();
for(int it2=0;it2<10000;it2++)
difference_omp(a,I,J,hx,hy);
clock_t end2=clock();
printf("Omp time=%fn",(float)(end2-start2)/CLOCKS_PER_SEC);
//output
output(a,X,Y,I,J);
//free memory
delete[] a;
delete[] X;
delete[] Y;
}
我写了一段代码来解决一个非常简单的二维拉普拉斯方程。尝试比较串行代码和OpenMP代码
我试图编译代码g++ tmp.cpp -fopenmp
并得到非常奇怪的结果输出:连续时间= 1.620000Omp时间= 9.820000
是否有人可以帮助我找出背后的原因是什么,以及如何纠正OpenMP代码
我遇到了有趣的结果。
luk32:~/projects/tests$ g++ -fopenmp -lgomp ./laplace.cpp
luk32:~/projects/tests$ ./a.out
Omp time=13.000000
Serial time=3.000000
luk32:~/projects/tests$ g++ -O3 -fopenmp -lgomp ./laplace.cpp
luk32:~/projects/tests$ ./a.out
Omp time=31.000000
Serial time=1.000000
因此,对于O3
, OpenMP的时间恶化,串行版本的时间下降。我的猜测是,问题实例非常小,以至于调用并行区域的实际开销在这里得到了体现。
您正在尝试并行处理在PC上花费1.5s/10k = 0.15毫秒的东西。初始化线程池和调度具有的开销,特别是对于schedule(dynamic)
我将尝试做一些测试来确认。不确定随机碰撞I
和J
是否合法。
:
OK,我切换J=I=10240;
并设置for(int it=0;it<50;it++)
。我还使用omp_get_wtime()
进行时间测量。下面是完整的diff文件。
结果如下:
Serial time=58.982189
Omp time=9.158118
它是在一个6-物理/12个逻辑核心的机器上执行的。现在,结果如预期的那样。您的示例问题对于OpenMP
来说太小了,以至于开销比计算时间还长。
Diff:
luk32:~/projects/tests$ diff laplace.orig.cpp laplace.cpp
88,89c88,89
< const int I=129;
< const int J=129;
---
> const int I=10000;
> const int J=10000;
102,103c102,103
< clock_t start=clock();
< for(int it=0;it<10000;it++)
---
> double start=omp_get_wtime();
> for(int it=0;it<50;it++)
105,106c105,106
< clock_t end=clock();
< printf("Serial time=%fn",(float)(end-start)/CLOCKS_PER_SEC);
---
> double end=omp_get_wtime();
> printf("Serial time=%fn",(float)(end-start));
110,111c110,111
< clock_t start2=clock();
< for(int it2=0;it2<10000;it2++)
---
> double start2=omp_get_wtime();
> for(int it2=0;it2<50;it2++)
113,114c113,114
< clock_t end2=clock();
< printf("Omp time=%fn",(float)(end2-start2)/CLOCKS_PER_SEC);
---
> double end2=omp_get_wtime();
> printf("Omp time=%fn",(float)(end2-start2));
编辑:我只是保留了主要问题,这样任何人遇到这个问题都会自动关注它。
相关文章:
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 我的字符计数代码计算错误.为什么
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 为什么我的代码在输出中增加了93天
- 为什么在这个代码结束循环中没有得到结束
- 为什么示例代码访问IUnknown中已删除的内存
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- 为什么在C的循环中使用printf的Rust代码不显示输出,而在C++的循环中显示std::cout
- 为什么模数运算符不适用于该代码
- 为什么catch中的代码没有被执行
- 这是什么代码?为什么它有效?C++
- 我遇到了一些C++代码.为什么我们必须在块中使用 *this 而不是这个
- 谁能解释这个代码?为什么显示 1
- 超级基本代码:为什么我的循环没有中断
- 琐碎的C++代码..为什么要编译
- 你能告诉我这个代码为什么崩溃吗
- 有人建议我的代码为什么在basic_ios和sstream中创建错误
- 我读取了一个char类型的变量,然后打印出ascii代码.为什么如果我按回车键,什么都没有
- 我为课堂编写了这个汉明编码代码.为什么这么慢