将 mpi 与 openMP 相结合
Combine mpi with openMP
我正在尝试使用 MPI、openMP 以及这两者的组合来解决问题。 MPI 和 openMP 都 运行ning 很好,但是当我尝试 MPI-openMP 版本的代码时,我无法通过 post.
末尾出现错误
MPI 版本
for(i=0;i<loop;i++)
{
for(j=start;j<end+1;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[(j-start)*3+0]-=G*mSquare/dCube*dx;
F[(j-start)*3+1]-=G*mSquare/dCube*dy;
F[(j-start)*3+2]-=G*mSquare/dCube*dz;
}
}
}
for(j=0;j<length;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
Cw[j*3+k]=C[(j+start)*3+k]+V[j*3+k]*dt;
}
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
loop
:描述该过程将发生的数量
- 由于
C
table 需要洞以获得正确的结果 start
& end
变量告诉每个节点 [=60] 的一部分=]负责
- 最后的
MPI_allgather
在新的i
循环开始前用存储在Cwtables中的新值更新Ctable
counts
变量是MPI_Allgather
将传输的数据大小,displs
在C
中的位置每个节点必须放Cw
数据
openMP 版本
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
for(i=0;i<loop;i++)
{
#pragma omp for schedule(static)
for(j=0;j<N;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[j*3+0]-=G*mSquare/dCube*dx;
F[j*3+1]-=G*mSquare/dCube*dy;
F[j*3+2]-=G*mSquare/dCube*dz;
}
}
}
#pragma omp for schedule(static)
for(j=0;j<N;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
C[j*3+k]=C[j*3+k]+V[j*3+k]*dt;
}
}
}
}
i
循环不能并行,因为每个循环都需要更新 C
,所以并行部分从 j
开始
合并版
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
for(i=0;i<loop;i++)
{
#pragma omp for schedule(static)
for(j=start;j<end+1;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[(j-start)*3+0]-=G*mSquare/dCube*dx;
F[(j-start)*3+1]-=G*mSquare/dCube*dy;
F[(j-start)*3+2]-=G*mSquare/dCube*dz;
}
}
}
#pragma omp for schedule(static)
for(j=0;j<length;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
Cw[j*3+k]=C[(j+start)*3+k]+V[j*3+k]*dt;
}
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
}
我在这里用 MPI
试图实现的是在每个节点中说 C
的 部分作为上面的 MPI 方法工作,然后是 openMP计算出Cw
tables对应这部分。然后 MPI 在 C
table 中收集 MPI_Allgather
的结果并重新开始 loop
次。问题是当我 运行 上面的代码出现此错误时:
Assertion failed in file src/mpid/ch3/src/ch3u_request.c at line 572: *(&incomplete) >= 0
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
= PID 10389 RUNNING AT felix-desktop
= EXIT CODE: 139
= CLEANING UP REMAINING PROCESSES
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions
问题出在 MPI_Allgather
行代码中,但我不知道是什么原因造成的。
您正在并行区域内调用 MPI_Allgather
。因此,多个线程使用相同的通信器(即 MPI_COMM_WORLD
)调用 MPI
例程,这是 MPI
不允许的标准。不过,您可以确保 MPI_Allgather
例程由单个线程调用:
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
...
#pragma omp master
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
#pragma omp barrier
}
通过添加 OpenMP
子句 master
可以确保只有一个线程调用 MPI_Allgather
( 即 master
线)。为确保您没有竞争条件(即, 线程更改将在 MPI_Allgatherv
MPI
调用中使用的内容)OpenMP barrier
是在 MPI_Allgather
之后添加的。因此,所有进程的所有线程都将等待,直到其进程的 master
线程完成执行 MPI_Allgather
调用。
如果您使用的 MPI 版本的线程支持级别为 MPI_THREAD_SERIALIZED,那么您可以使用构造函数 single
而不是 master
。确保 MPI 实现的线程支持级别至少为 MPI_THREAD_FUNNELED
.
另一种方法是将MPI_Allgather
例程移动到并行区域之外:
for(i=0;i<loop;i++)
{
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a){
...
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
由于 体面的 OpenMP 实现将使用线程池,因此只初始化线程一次,因此应该可以减少多个并行区域创建开销。
我正在尝试使用 MPI、openMP 以及这两者的组合来解决问题。 MPI 和 openMP 都 运行ning 很好,但是当我尝试 MPI-openMP 版本的代码时,我无法通过 post.
末尾出现错误MPI 版本
for(i=0;i<loop;i++)
{
for(j=start;j<end+1;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[(j-start)*3+0]-=G*mSquare/dCube*dx;
F[(j-start)*3+1]-=G*mSquare/dCube*dy;
F[(j-start)*3+2]-=G*mSquare/dCube*dz;
}
}
}
for(j=0;j<length;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
Cw[j*3+k]=C[(j+start)*3+k]+V[j*3+k]*dt;
}
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
loop
:描述该过程将发生的数量- 由于
C
table 需要洞以获得正确的结果start
&end
变量告诉每个节点 [=60] 的一部分=]负责 - 最后的
MPI_allgather
在新的i
循环开始前用存储在Cwtables中的新值更新Ctable counts
变量是MPI_Allgather
将传输的数据大小,displs
在C
中的位置每个节点必须放Cw
数据
openMP 版本
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
for(i=0;i<loop;i++)
{
#pragma omp for schedule(static)
for(j=0;j<N;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[j*3+0]-=G*mSquare/dCube*dx;
F[j*3+1]-=G*mSquare/dCube*dy;
F[j*3+2]-=G*mSquare/dCube*dz;
}
}
}
#pragma omp for schedule(static)
for(j=0;j<N;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
C[j*3+k]=C[j*3+k]+V[j*3+k]*dt;
}
}
}
}
i
循环不能并行,因为每个循环都需要更新 C
,所以并行部分从 j
合并版
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
for(i=0;i<loop;i++)
{
#pragma omp for schedule(static)
for(j=start;j<end+1;j++)
{
for(k=0;k<N;k++)
{
if(j!=k)
{
dx=C[k*3+0]-C[j*3+0];
dy=C[k*3+1]-C[j*3+1];
dz=C[k*3+2]-C[j*3+2];
d=sqrt(pow(dx,2)+pow(dy,2)+pow(dz,2));
dCube=pow(d,3);
mSquare=pow(m,2);
F[(j-start)*3+0]-=G*mSquare/dCube*dx;
F[(j-start)*3+1]-=G*mSquare/dCube*dy;
F[(j-start)*3+2]-=G*mSquare/dCube*dz;
}
}
}
#pragma omp for schedule(static)
for(j=0;j<length;j++)
{
for(k=0;k<3;k++)
{
a=F[j*3+k]/m;
V[j*3+k]=V[j*3+k]+a*dt;
Cw[j*3+k]=C[(j+start)*3+k]+V[j*3+k]*dt;
}
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
}
我在这里用 MPI
试图实现的是在每个节点中说 C
的 部分作为上面的 MPI 方法工作,然后是 openMP计算出Cw
tables对应这部分。然后 MPI 在 C
table 中收集 MPI_Allgather
的结果并重新开始 loop
次。问题是当我 运行 上面的代码出现此错误时:
Assertion failed in file src/mpid/ch3/src/ch3u_request.c at line 572: *(&incomplete) >= 0
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
= PID 10389 RUNNING AT felix-desktop
= EXIT CODE: 139
= CLEANING UP REMAINING PROCESSES
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGESYOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions
问题出在 MPI_Allgather
行代码中,但我不知道是什么原因造成的。
您正在并行区域内调用 MPI_Allgather
。因此,多个线程使用相同的通信器(即 MPI_COMM_WORLD
)调用 MPI
例程,这是 MPI
不允许的标准。不过,您可以确保 MPI_Allgather
例程由单个线程调用:
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a)
{
...
#pragma omp master
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
#pragma omp barrier
}
通过添加 OpenMP
子句 master
可以确保只有一个线程调用 MPI_Allgather
( 即 master
线)。为确保您没有竞争条件(即, 线程更改将在 MPI_Allgatherv
MPI
调用中使用的内容)OpenMP barrier
是在 MPI_Allgather
之后添加的。因此,所有进程的所有线程都将等待,直到其进程的 master
线程完成执行 MPI_Allgather
调用。
如果您使用的 MPI 版本的线程支持级别为 MPI_THREAD_SERIALIZED,那么您可以使用构造函数 single
而不是 master
。确保 MPI 实现的线程支持级别至少为 MPI_THREAD_FUNNELED
.
另一种方法是将MPI_Allgather
例程移动到并行区域之外:
for(i=0;i<loop;i++)
{
#pragma omp parallel private(i,k,dx,dy,dz,d,dCube,mSquare,a){
...
}
MPI_Allgatherv(&Cw[0],length*3,MPI_DOUBLE,&C[0],counts,displs,MPI_DOUBLE,MPI_COMM_WORLD);
}
由于 体面的 OpenMP 实现将使用线程池,因此只初始化线程一次,因此应该可以减少多个并行区域创建开销。