C++ pmpi_聚集中出现致命错误

C++ pmpi_聚集中出现致命错误,c++,runtime-error,openmpi,mpich,C++,Runtime Error,Openmpi,Mpich,我正在编写一个光线跟踪器,它编译得很好,但是当我使用MPI_Gather()函数时,我得到了这个错误集。如果我写文件,整个过程会很顺利,但是我不能在分布式计算系统上运行它 Fatal error in PMPI_Gather: Internal MPI error!, error stack: PMPI_Gather(856)......: MPI_Gather(sbuf=0x8e05468, scount=882000, MPI_BYTE, rbuf=0x8df7628, rcount=

我正在编写一个光线跟踪器,它编译得很好,但是当我使用MPI_Gather()函数时,我得到了这个错误集。如果我写文件,整个过程会很顺利,但是我不能在分布式计算系统上运行它

Fatal error in PMPI_Gather: Internal MPI error!, error stack:
PMPI_Gather(856)......:
   MPI_Gather(sbuf=0x8e05468, scount=882000, MPI_BYTE, rbuf=0x8df7628, rcount=882000, MPI_BYTE, root=0, MPI_COMM_WORLD) failed
MPIR_Gather_impl(681).: 
MPIR_Gather(641)......: 
MPIR_Gather_intra(152): 
MPIR_Localcopy(378)...:
   memcpy arguments alias each other, dst=0x8df7628 src=0x8e05468 len=882000

===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   EXIT CODE: 1
=   CLEANING UP REMAINING PROCESSES
=   YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
我不太清楚这个错误是什么意思,所以很难绕开它

以下是主要功能的来源:

int main(int argc, char **argv) {
  clock_t total_time = clock(), otime;
  init_MPI(argc, argv);   //Initialize OpenMPI
  glutInit(&argc,argv);

  get_params(argc, argv);   //Get parameters from command line
  if (buildScene(scene, cam) == -1) MPI_Abort(MPI_COMM_WORLD,rc); exit(1);
  samples = samples > 0 ? whitted ? 1 : samples : 1;
  if (numprocs == 1) {
    scn = new RGBApixmap(h,w);
    raytrace(h,scn);
    if (smult > 1) *scn = scaleImage(scn,smult);
  } else {
    int rows = h / numprocs;
    subscn = new RGBApixmap(rows,w);
    raytrace(rows, subscn);
    if (smult > 1) *subscn = scaleImage(subscn,smult);

    if (pid == MASTER) scn = new RGBApixmap(h/smult,w/smult);
    MPI_Gather(subscn,rows/smult*w,MPI_BYTE,scn,rows/smult*w,MPI_BYTE,MASTER,MPI_COMM_WORLD);
  }
  if (pid == MASTER) {
    initGlut(argc, argv);
    glutMainLoop();
  }
  MPI_Finalize();
  return 0;
}
编辑:

我已修复该问题,并在下面发布了更新的代码:

int main(int argc, char **argv) {
  clock_t total_time = clock(), otime;
  init_MPI(argc, argv);
  glutInit(&argc,argv);    
  bool OK = get_params(argc, argv);
  if (buildScene(scene, cam) == -1) { MPI_Abort(MPI_COMM_WORLD,rc); exit(1); }
  samples = samples > 0 ? whitted ? 1 : samples : 1;
  int rows = h / numprocs;
  subscn = new RGBApixmap(rows,w);
  raytrace(rows, subscn);
  MPI_Barrier(MPI_COMM_WORLD);          /* Synchronize all processes */   
  if (smult > 1) *subscn = scaleImage(subscn,smult); 
  MPI_Barrier(MPI_COMM_WORLD);          /* Synchronize all processes */

  int nElts = subscn->getWidth()*subscn->getHeight();
  RGBA *subscnpix, *scnpix;
  subscnpix = subscn->getPixs();
  scnpix = (RGBA*)malloc(sizeof(RGBA)*((w/smult)*(h/smult)));

  MPI_Datatype pixel;
  MPI_Type_contiguous(4,MPI_UNSIGNED_CHAR,&pixel);
  MPI_Type_commit(&pixel);

  MPI_Gather(subscnpix,nElts,pixel,scnpix,nElts,pixel,MASTER,MPI_COMM_WORLD);

  scn = new RGBApixmap(h/smult,w/smult,scnpix);

  MPI_Type_free(&pixel);

  MPI_Barrier(MPI_COMM_WORLD);          /* Synchonize all processes */
  if (pid == MASTER) {
    initGlut(argc, argv);
    glutMainLoop();
  }
  MPI_Finalize();
  return 0;
}

调用
MPI\u Gather
中的秩
MASTER
中的发送和接收缓冲区重叠,这违反了MPI标准施加的限制
subscn
位于
0x8e05468
,而
scn
位于
0x8df7628
。从
0x8df7628
0x8e05468
的内存范围仅为56896字节,您尝试向其写入882000次
numprocs
字节,但这不起作用

这是因为您将行数除以比例因子,但仍然忘记将图像宽度
w
除以比例因子

MPI_聚集(子CN,行/smult*w/smult,MPI_字节,
scn,行/smult*w/smult,MPI_字节,
硕士,MPI_COMM_WORLD);

请注意,如果pixmap不是灰度图,您还必须将数据元素的数量乘以颜色分量的数量(可能还包括一个alpha通道),或者创建一个连续的派生数据类型。

我尝试了您建议的更改,但仍然出现相同的错误。如何创建连续的派生数据类型?我建议您在所有列中打印
w
smult
的值,并查看计算是否合理。您的图像是彩色的还是灰度的?它是彩色的,带有红色、绿色、蓝色和alpha值。我查阅了如何生成派生数据类型,并为我的问题找到了解决方法;我已经用固定代码更新了我的原始问题。我的RGBApixmap类包含一个像素数组,因此我认为它试图传递像素数组
行/smult*w/smult
次,这导致了内存跨度重叠。感谢您的帮助。对MPI\U屏障的三个调用是不必要的。您的进程仅在
MPI\u Gather
调用中交换数据,而此调用是集体调用,即它将等待所有进程签入,然后在根节点完成。另外,不要使用
clock()
,因为这是非常不可移植的,而且它不测量挂钟时间(在Unix上,它测量的CPU时间与在Windows上测量的时间不同)。改为使用
MPI\u Wtime()
。我知道我对
MPI\u Barrier
的调用是不必要的,我在编写文件作为调试步骤时就已经在那里了,当时我无法让MPI\u Gather工作。我对
clock()
的调用是在我将代码重写为OpenMPI之前遗留下来的,我更担心的是
MPI\u-Gather
能否正常工作,而不是直到现在才将它们更改为
MPI\u-Wtime()
,但感谢您指出这一点。