OpenMP 代码帮助
Posted
技术标签:
【中文标题】OpenMP 代码帮助【英文标题】:OpenMP help on code 【发布时间】:2012-03-24 11:12:33 【问题描述】:这是我第一次发帖,所以我会为我的新手错误道歉。还请原谅并非所有变量名称都是英文的事实。我的问题如下:我在 Visual Studio 2010 和 eclipse 中使用 cygwin gcc 编译器工具链在 c/c++ 中使用 openMP 编写了此代码。在视觉上我得到了加速,但在日食中我得到了两倍于串行版本的减速。有人可以解释一下我做错了什么吗?简而言之,我只是在模拟从 3D 矢量数组复制到双精度数组以通过 MPI 发送时的加速。
#include <omp.h>
#include <time.h>
#include <stdio.h>
#include <vector>
const int NUMAR_FORME=10;
const int NUMAR_SECUNDE_SIMULATE=60; //number of buffers
const int dimensiuni_forme[10]=100,200,300,400,500,600,700,800,900,10000; //size of each buffer
//-------- the buffers, cuurently only worker_buffer and buff is used
std::vector<std::vector<std::vector<double> > > worker_buffer;
std::vector<std::vector<double> > send_buffer,corect;
double **buff;
double **worker_buffer1;
long i,j,k,l;
int flag=0;
int numarator=0; //number of tests runed
clock_t start;
start=clock();
worker_buffer.resize(1);
buff = new double* [2];
int de_scris=0; //this tells me in which buffer to store, nou I alternate buff[0], buff[1], buff[0], buff[1]
worker_buffer[0].resize(NUMAR_SECUNDE_SIMULATE);
for(i=0;i<NUMAR_SECUNDE_SIMULATE;i++)
worker_buffer[0][i].resize(dimensiuni_forme[9]);
while(numarator<60)
if(numarator!=0)
delete [] buff[de_scris];
if(numarator!=0)
de_scris=(de_scris+1)%2;
long limita;
limita=NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3; //3-comes from the fact that I will have a 3D vector structure
buff[de_scris]= new double [limita];
for(i=0;i<NUMAR_SECUNDE_SIMULATE;i++)
for(j=0;j<dimensiuni_forme[9];j++)
worker_buffer[0][i][j]=(i*dimensiuni_forme[9]+j)*3;
buff[de_scris][(i*dimensiuni_forme[9]+j)*3]=worker_buffer[0][i][j];
buff[de_scris][(i*dimensiuni_forme[9]+j)*3+1]=worker_buffer[0][i][j]+0.5;
buff[de_scris][(i*dimensiuni_forme[9]+j)*3+2]=worker_buffer[0][i][j]+0.75;
numarator++;
start=clock()-start;
printf("TICKS TOTAL %ld \n",start);
bool ad=true;
long nr;
for(i=0;i<NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3;i++)
if(i%3==0)
nr=i;
if(i%3==0 && buff[de_scris][i]!=i)
ad=false;
else
if(i%3==1 &&buff[de_scris][i]!=(nr+0.5))
ad=false;
else
if(i%3==2 && buff[de_scris][i]!=(nr+0.75))
ad=false;
if(ad==false)
printf("not correct \n");
start=clock();
numarator=0;
//parallel version
while(numarator<60)
if(numarator!=0)
delete [] buff[de_scris];
long index, limita,id;
omp_set_num_threads(2);
if(numarator!=0)
de_scris=(de_scris+1)%2;
limita=NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3; //3-
buff[de_scris]= new double [limita];
#pragma omp parallel shared(worker_buffer,limita,buff) private(index,id)
printf("intram cu %d threaduri \n", omp_get_num_threads());
id=omp_get_thread_num();
//index=id;
for(index=id;(index*3)<limita;index+=omp_get_num_threads())
buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x
buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5;
buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75;
// index+=omp_get_num_threads();
//end parallel zone
numarator++;
start=clock()-start;
printf("TICKS TOTAL %ld \n",start);
ad=true;
//testing for correctness
for(i=0;i<NUMAR_SECUNDE_SIMULATE*dimensiuni_forme[9]*3;i++)
if(i%3==0)
nr=i;
if(i%3==0 && buff[de_scris][i]!=i)
ad=false;
else
if(i%3==1 &&buff[de_scris][i]!=(nr+0.5))
ad=false;
else
if(i%3==2 && buff[de_scris][i]!=(nr+0.75))
ad=false;
if(ad==false)
printf("not correct \n");
return 0;
【问题讨论】:
您是否仅使用代码中的时钟功能来测量时间?如果是这样,您应该知道时钟返回使用的 cpu 时间,这意味着如果您使用 2 个处理器,clock() 返回的时间将增加两倍于实际时间。我不能 100% 确定 visucal c++ 是否以相同的方式实现 clock() 函数,这可能是您测量不同时间的原因。 我试过使用 time() 和 clock_gettime() 结果是一样的 【参考方案1】:从你组织这个 for 循环的方式来看:
for(index=id;(index*3)<limita;index+=omp_get_num_threads())
buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x
buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5;
buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75;
假设您有 4 个线程,您的线程将获得交错的索引值:
thread 0: 0, 4, 8, 12,...
thread 1: 1, 5, 9, 13,...
thread 2: 2, 6, 10, 14,...
thread 3: 3, 7, 11, 15,...
这可能会导致缓存乒乓效应,因为不同线程写入的值可能会落在同一缓存行上,从而减慢您的执行速度。
尝试使用带有静态分区的简单 for 循环,以获得连续分区:
#pragma omp parallel for
for(index = 0; index < limita / 3;index++)
buff[de_scris][index*3]=worker_buffer[0][index/dimensiuni_forme[9]][index%dimensiuni_forme[9]]; //aici va veni send_buff[index].x
buff[de_scris][index*3+1]=buff[de_scris][index*3]+0.5;
buff[de_scris][index*3+2]=buff[de_scris][index*3]+0.75;
【讨论】:
你是对的,非常感谢,我使用了你写的循环,它显示出加速。奇怪的是,它在不使用 for 指令的情况下如何在视觉上显示速度。 @Ray:很高兴为您提供帮助。如果它解决了您的问题,请不要忘记接受答案。以上是关于OpenMP 代码帮助的主要内容,如果未能解决你的问题,请参考以下文章