通过MPI发送c结构部分失败

通过MPI发送c结构部分失败,c,struct,mpi,C,Struct,Mpi,我正在使用MPI\u Type\u create\u struct()发送一个(粒子)结构,如已完成或详细说明。 我正在收集所有要进入特定进程的粒子,memcpy()将它们收集到发送缓冲区中,然后MPI\u Isend()将它们收集起来 到目前为止,一切顺利MPI_Iprob()'ing为消息提供正确的发送粒子数。 因此,我MPI_Recv()缓冲区并提取数据(现在甚至通过逐个复制结构)。无论我发送多少粒子,只有第一个粒子的数据是正确的 有三种可能的错误: MPI\u Type\u create

我正在使用
MPI\u Type\u create\u struct()
发送一个(粒子)结构,如已完成或详细说明。 我正在收集所有要进入特定进程的粒子,
memcpy()
将它们收集到发送缓冲区中,然后
MPI\u Isend()
将它们收集起来

到目前为止,一切顺利
MPI_Iprob()
'ing为消息提供正确的发送粒子数。 因此,我
MPI_Recv()
缓冲区并提取数据(现在甚至通过逐个复制结构)。无论我发送多少粒子,只有第一个粒子的数据是正确的

有三种可能的错误:

  • MPI\u Type\u create\u struct()
    无法创建我的结构的正确映射,因为我在第一个链接中使用了
    offset of()
    。可能我的结构包含一个不可见的填充,如第二个链接中所述
  • 在将粒子复制到发送缓冲区和从接收缓冲区复制回来时,我犯了一些简单的错误(我确实打印了发送缓冲区,而且它工作正常,但可能我忽略了一些东西)
  • 完全不同的东西 (很抱歉,代码的显示非常难看,我无法以下降方式显示它。您也可以在Github上找到代码-行已经标记了!)

    以下是mpi数据类型的构造

    typedef结构{
    int-ID;
    双x[DIM];
    }p相粒子;
    const int items=2;
    int block_length[2]={1,DIM};
    MPI_数据类型MPI_类型[2]={MPI_INT,MPI_DOUBLE};
    MPI_Aint偏移量[2];
    偏移量[0]=偏移量(pchase\u particle\u t,ID);
    偏移量[1]=偏移量(pchase\u particle\u t,x);
    MPI\u类型\u创建\u结构(项目、块长度、偏移、MPI\u类型,&W->MPI\u粒子);
    MPI_类型_提交(&W->MPI_粒子);
    
    派遣

    /*处理所有mpi发送/接收状态数据*/
    MPI_请求*发送_请求=P4EST_ALLOC(MPI_请求,W->P4EST->mpisize);
    MPI_状态*recv_状态=P4EST_ALLOC(MPI_状态,W->P4EST->mpisize);
    /*设置发送/接收缓冲区*/
    pchase\u particle\u t**recv\u buf=P4EST\u ALLOC(pchase\u particle\u t*,数量发送器);
    pchase\u particle\u t**send\u buf=P4EST\u ALLOC(pchase\u particle\u t*,num\u receiver);
    int recv_count=0,recv_长度,标志,j;
    /*将所有粒子发送到它们所属的进程*/
    对于(i=0;iparticles_to,receivers[i]);
    Phase_particle_t*tmpParticle;
    int send_count=0;
    /*为要发送的粒子获取空间*/
    send_buf[i]=P4EST_ALLOC(pchase_particle,tmpList->elem_count);
    /*将所有粒子复制到发送缓冲区,并从此过程中移除它们*/
    while(tmpList->first!=NULL){
    tmpParticle=sc_list_pop(tmpList);
    memcpy(send_buf[i]+send_count*sizeof(pchase_particle_t)、tmpParticle、sizeof(pchase_particle_t));
    /*自由粒子*/
    P4EST_FREE(tmpParticle);
    /*更新粒子计数器*/
    发送_计数++;
    }
    /*打印发送缓冲区*/
    对于(j=0;jp4est->mpirank,tmpParticle->ID,tmpParticle->x[0],tmpParticle->x[1]);
    }
    printf(“[pchase%i sending]粒子数:%i\n”,W->p4est->mpirank,send\u count);
    /*将粒子发送给右所有者*/
    mpiret=MPI Isend(发送buf[i],发送计数,W->MPI\u粒子,接收器[i],13,W->p4est->mpicomm,&send\u请求[i]);
    SC检查MPI(mpiret);
    }
    
    还有接球

    recv_count=0;
    /*在所有邮件到达之前检查邮件*/
    while(recv_countp4est->mpicomm,
    &标志和记录状态[i];
    国际单项体育联合会(旗){
    /*解析接收到的粒子数*/
    MPI_获取_计数(&recv_状态[i],W->MPI_粒子和&recv_长度);
    printf(“[pchase%i receiving message]%i粒子从发件人%i到达,标记为%i\n”,
    W->p4est->mpirank,recv_长度,recv_状态[i]。MPI_源,recv_状态[i]。MPI_标记);
    /*为要发送的粒子获取空间*/
    recv_buf[recv_count]=P4EST_ALLOC(pchase_particle_t,recv_length);
    /*接收包含recv_长度粒子的列表*/
    mpiret=MPI\u Recv(Recv\u buf[Recv\u count],Recv\u长度,W->MPI\u粒子,Recv\u状态[i]。MPI\u源,
    recv_status[i].MPI_标记,W->p4est->mpicomm,&recv_status[i]);
    SC检查MPI(mpiret);
    /*
    *将所有接收到的粒子插入到
    *推送列表
    */
    Phase_particle_t*tmpParticle;
    对于(j=0;jID=tmpParticle->ID;
    addParticle->x[0]=tmpParticle->x[0];
    addParticle->x[1]=tmpParticle->x[1];
    printf(“[pchase%i接收]粒子[%i](%lf,%lf)\n”,
    W->p4est->mpirank,addParticle->ID,addParticle->x[0],addParticle->x[1]);
    /*将接收到的粒子推送到推送列表并更新世界计数器*/
    sc\u list\u append(W->particle\u push\u list,addParticle);
    W->n_粒子++;
    }
    /*我们收到了另一个粒子列表*/
    recv_count++;
    }
    }
    }
    
    编辑:重新凹入。。
    编辑:只有第一个粒子的数据是正确的,这意味着它的所有属性(ID和坐标)都与发送的粒子的属性相同。然而,其他的用零初始化,即ID=0,x[0]=0.0,x[1]=0.0。也许这是解决问题的一个暗示

    指针中有错误
    /* handle all mpi send/recv status data */
    MPI_Request        *send_request = P4EST_ALLOC(MPI_Request, W->p4est->mpisize);
    MPI_Status         *recv_status = P4EST_ALLOC(MPI_Status, W->p4est->mpisize);
    /* setup send/recv buffers */
    pchase_particle_t **recv_buf = P4EST_ALLOC(pchase_particle_t *, num_senders);
    pchase_particle_t **send_buf = P4EST_ALLOC(pchase_particle_t *, num_receivers);
    int                 recv_count = 0, recv_length, flag, j;
    
    /* send all particles to their belonging procs */
    for (i = 0; i < num_receivers; i++) {
      /* resolve particle list for proc i */
      sc_list_t          *tmpList = *((sc_list_t **) sc_array_index(W->particles_to, receivers[i]));
      pchase_particle_t * tmpParticle;
      int                 send_count = 0;
    
      /* get space for the particles to be sent */
      send_buf[i] = P4EST_ALLOC(pchase_particle_t, tmpList->elem_count);
    
      /* copy all particles into the send buffer and remove them from this proc */
      while(tmpList->first != NULL){
        tmpParticle = sc_list_pop(tmpList);
        memcpy(send_buf[i] + send_count * sizeof(pchase_particle_t), tmpParticle, sizeof(pchase_particle_t));
        /* free particle */
        P4EST_FREE(tmpParticle);
        /* update particle counter */ 
        send_count++;
      }
    
      /* print send buffer */
      for (j = 0; j < send_count; j++) {
        pchase_particle_t  *tmpParticle = send_buf[i] + j * sizeof(pchase_particle_t);
        printf("[pchase %i sending] particle[%i](%lf,%lf)\n", W->p4est->mpirank, tmpParticle->ID, tmpParticle->x[0], tmpParticle->x[1]);
      }
    
      printf("[pchase %i sending] particle count: %i\n", W->p4est->mpirank, send_count);
      /* send particles to right owner */
      mpiret = MPI_Isend(send_buf[i], send_count, W->MPI_Particle, receivers[i], 13, W->p4est->mpicomm, &send_request[i]);
      SC_CHECK_MPI(mpiret);
    }