用了openmp后效率更低,问什么?

hustwjz 2009-12-31 01:10:27
如下代码是从两个文件中读取数据的程序,一个没有用多线程,一个用了多线程,后者反而比前者慢了3倍。各位帮我分析一下原因:
DWORD preTick = GetTickCount();

// read the geometry input file
ifstream streamGeom;
streamGeom.open(geomFile);
int numOfTriangles = 0;
streamGeom >> numOfTriangles;

F3d* vertexBuffer = new F3d[numOfTriangles * 3];
for (int i = 0; i < numOfTriangles * 3; i++)
{
streamGeom >> vertexBuffer[i].x >> vertexBuffer[i].y >> vertexBuffer[i].z;
}

streamGeom.close();

// read the ray input file
ifstream streamRay;
streamRay.open(rayFile);
int numOfRays = 0;
streamRay >> numOfRays;
F3d* rayOrigins = new F3d[numOfRays];
F3d* rayDirections = new F3d[numOfRays];

for (int i = 0; i < numOfRays; i++)
{
streamRay >> rayOrigins[i].x >> rayOrigins[i].y >> rayOrigins[i].z;
streamRay >> rayDirections[i].x >> rayDirections[i].y >> rayDirections[i].z;
}

streamRay.close();
多线程的代码:
DWORD preTick = GetTickCount();

// read the geometry input file
ifstream fstreamGeom;
fstreamGeom.open(geomFile);
ostringstream ostreamGeom;
ostreamGeom << fstreamGeom.rdbuf();
istringstream streamGeom(ostreamGeom.str());
fstreamGeom.close();

ifstream fstreamRay;
fstreamRay.open(rayFile);
ostringstream ostreamRay;
ostreamRay << fstreamRay.rdbuf();
istringstream streamRay(ostreamRay.str());
fstreamRay.close();

int numOfTriangles = 0;
streamGeom >> numOfTriangles;
F3d* vertexBuffer = new F3d[numOfTriangles * 3];

int numOfRays = 0;
streamRay >> numOfRays;
F3d* rayOrigins = new F3d[numOfRays];
F3d* rayDirections = new F3d[numOfRays];

printf( "Read time=%d\n", GetTickCount()-preTick);
preTick = GetTickCount();
#pragma omp parallel sections
{
#pragma omp section
{
for (int i = 0; i < numOfTriangles * 3; i++)
{
streamGeom >> vertexBuffer[i].x >> vertexBuffer[i].y >> vertexBuffer[i].z;
}
}

#pragma omp section
{
for (int i = 0; i < numOfRays; i++)
{
streamRay >> rayOrigins[i].x >> rayOrigins[i].y >> rayOrigins[i].z;
streamRay >> rayDirections[i].x >> rayDirections[i].y >> rayDirections[i].z;
}
}
}

printf( "Read time=%d\n", GetTickCount()-preTick);
...全文
939 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
intel_iclifort 2010-01-18
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 hustwjz 的回复:]
首先,我已经避免了硬盘的IO,其次在sections中我已经启用了两个线程。问题的关键在于stringstream。放弃

关于公司的比赛,我已经退出了。刚在网上贴了个帖子就被人骂作“公司的土人”,如果参加竞赛,还不知道会被人骂成什么样子。不过这个竞赛题,我觉得不错。
我以前都是用WinAPI写多线程,OpenMP提供了一个完全不同的多线程编程方法。为了解决stingstream性能降低的问题,我查阅了许多与false sharing相关的文档。
我是数学盲,为了计算交点,我复习了下大学数学,完全自己实现了相关算法。后来在网上搜到了一篇论文,实现了那篇论文中提到的算法。
总体来说,我享受整个过程,但是我不关心竞赛的结果。

[/Quote]

非常欢迎你来论坛里交流你遇到的问题, 这种讨论对其它人也是非常有帮助的

OpenMP只是并行化编程方法的一种, 大家都在学习, 总结经验, 不断提高

加分鼓励了
横云断岭 2010-01-16
  • 打赏
  • 举报
回复
我再看了下自己的回复,发现错了。。实在是不好意思。
#pragma omp section
这个不是把for并行化执行。。
以前只知道#pragma omp parallel for,今天才发现自己实在太菜了。。
潜水。
hustwjz 2010-01-15
  • 打赏
  • 举报
回复
首先,我已经避免了硬盘的IO,其次在sections中我已经启用了两个线程。问题的关键在于stringstream。放弃

关于公司的比赛,我已经退出了。刚在网上贴了个帖子就被人骂作“公司的土人”,如果参加竞赛,还不知道会被人骂成什么样子。不过这个竞赛题,我觉得不错。
我以前都是用WinAPI写多线程,OpenMP提供了一个完全不同的多线程编程方法。为了解决stingstream性能降低的问题,我查阅了许多与false sharing相关的文档。
我是数学盲,为了计算交点,我复习了下大学数学,完全自己实现了相关算法。后来在网上搜到了一篇论文,实现了那篇论文中提到的算法。
总体来说,我享受整个过程,但是我不关心竞赛的结果。
Ahxing1985 2010-01-11
  • 打赏
  • 举报
回复
你一定是在参加我们公司多核比赛的,我说怎么这个程序有点眼熟呢。我也遇到同样的问题,在双核中OMP一点用都没有。
横云断岭 2010-01-11
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 hustwjz 的回复:]
并行没有任何问题,我放弃stream用c函数重写了上述代码后,效率提高了大概40%
[/Quote]
我的意思是你的这段代码问题
#pragma omp parallel sections 
{
#pragma omp section
{
for (int i = 0; i < numOfTriangles * 3; i++)
{
streamGeom >> vertexBuffer[i].x >> vertexBuffer[i].y >> vertexBuffer[i].z;
}
}

#pragma omp section
{
for (int i = 0; i < numOfRays; i++)
{
streamRay >> rayOrigins[i].x >> rayOrigins[i].y >> rayOrigins[i].z;
streamRay >> rayDirections[i].x >> rayDirections[i].y >> rayDirections[i].z;
}
}


我觉得这里应该是用两个线程来分工,一个执行这个:
streamGeom >> vertexBuffer[i].x >> vertexBuffer[i].y >> vertexBuffer[i].z;
另一个来执行这个:
streamRay >> rayOrigins[i].x >> rayOrigins[i].y >> rayOrigins[i].z;
streamRay >> rayDirections[i].x >> rayDirections[i].y >> rayDirections[i].z;
而不是把上面的两个都变成多线程。
用C的函数来读文件的确比C++快很多。。
Intel_CG 2010-01-11
  • 打赏
  • 举报
回复
硬盘IO是串行的,两个线程只是增加冲突,并相互干扰。
DemonWhisper 2010-01-09
  • 打赏
  • 举报
回复
我突然发现,这个比赛很没有意思
完全是char* => float

float => char
float => char*
看谁转的看,谁就赢了。
挖槽
我们公司的土人
hustwjz 2010-01-09
  • 打赏
  • 举报
回复
并行没有任何问题,我放弃stream用c函数重写了上述代码后,效率提高了大概40%
横云断岭 2010-01-02
  • 打赏
  • 举报
回复
我觉得,是你的并行不好。
应该有两个进程,一个进程读写一个文件,这样应该可以提高速度。
但是好像你的是把for循环那里并行化了。这样貌似是对一个文件的读写进行了并行化。
这样应该要互斥下?不知道你有没有检查过读出的数据正确不?
希望没看错代码。。囧。。
hustwjz 2009-12-31
  • 打赏
  • 举报
回复
对于第二段代码,如果禁止openmp,总时间为940ms.
所以问题完全在于并行的两个section
hustwjz 2009-12-31
  • 打赏
  • 举报
回复
前面代码读取文件总时间870ms
后面代码:
读取文件时间:94ms
从stream读入数据时间:5400ms
taodm 2009-12-31
  • 打赏
  • 举报
回复
你的方法1也要先读到stringstream后才有可比性。
另外,后面半段的处理耗时多少啊?
hustwjz 2009-12-31
  • 打赏
  • 举报
回复
ifstream fstreamRay;
fstreamRay.open(rayFile);
ostringstream ostreamRay;
ostreamRay < < fstreamRay.rdbuf();
istringstream streamRay(ostreamRay.str());
fstreamRay.close();

这段代码就是将文件读入到内存,然后利用ostringstream进行数据操作
hustwjz 2009-12-31
  • 打赏
  • 举报
回复
数据已经提前读取到内存了,并行部分针对内存操作。这难道有什么依赖吗?
taodm 2009-12-31
  • 打赏
  • 举报
回复
囧,那“一个硬盘”的超强依赖关系你还真能当看不见呀。
hustwjz 2009-12-31
  • 打赏
  • 举报
回复
一个硬盘,双核
这两个并行的section没有任何依赖关系速度,按道理将可以提高一倍
taodm 2009-12-31
  • 打赏
  • 举报
回复
呃,你机器几个硬盘?raid几的?几个cpu?
哪个家伙和你上辈子就结了仇,告诉你说用了openmp就可以快的?

24,860

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧