OpenMPI 不允许在任何相应的非阻塞原语之前调用 MPI_Wait?

cpp*_*ame 1 mpi nonblocking segmentation-fault openmpi

我的应用程序与 LAM/MPI 一起工作,但它与 OpenMPI 一起崩溃。

下面是我的代码的外观。

void Comm::nonblocking_send( int s_idx , int e_idx )
{      
      MPI_Wait(&mpireq,&mpistat);


      buffer.clear();

      list<class vertex*>::iterator vit;

      for( vit=our_dag->cur_block_intmeds.begin() ; vit!=our_dag->cur_block_intmeds.end() ; vit++ )
      {
        vertex * v = (*vit);

        list<class edge*> in_edges = v->in_edges;
        list<class edge*>::iterator eit;

        for( eit=in_edges.begin() ; eit!=in_edges.end() ; eit++ )
        {
            int x_idx = (*eit)->src->idx;
            int     y_idx = (*eit)->tgt->idx;
            double  dydx  = (*eit)->partial;

            struct partial * p = new partial();
            //ownership info
            p->rank = our_dag->rank;
            //structural info
            p->x_idx = x_idx;
            p->y_idx = y_idx;
            p->dydx = dydx;
            //block info
            p->block_idx = our_dag->block_idx;
            p->s_idx = s_idx;
            p->e_idx = e_idx;

            buffer.push_back(*p);

            delete p;
        }
      }

      MPI_Isend( &buffer[0] , buffer.size() , MPI_PARTIAL , 0 , DAG_MERG_REQ ,   MPI_COMM_WORLD , &mpireq );    
}
Run Code Online (Sandbox Code Playgroud)

如您所见,在函数开始时,会调用 MPI_Wait,然后进行一些计算,并最终在函数末尾调用相应的 MPI_ISend。

每次使用 OpenMPI 运行时,我都会从 MPI_Wait 中收到分段错误。

我通过检查是否第一次使用布尔变量*first_time*调用函数来解决这个问题,如下所示。

void Comm::nonblocking_send( int s_idx , int e_idx )
    {      
          if(first_time)

               first_time = false;
          else

               MPI_Wait(&mpireq,&mpistat);


          buffer.clear();

          list<class vertex*>::iterator vit;

          for( vit=our_dag->cur_block_intmeds.begin() ; vit!=our_dag->cur_block_intmeds.end() ; vit++ )
          {
            vertex * v = (*vit);

            list<class edge*> in_edges = v->in_edges;
            list<class edge*>::iterator eit;

            for( eit=in_edges.begin() ; eit!=in_edges.end() ; eit++ )
            {
                int x_idx = (*eit)->src->idx;
                int     y_idx = (*eit)->tgt->idx;
                double  dydx  = (*eit)->partial;

                struct partial * p = new partial();
                //ownership info
                p->rank = our_dag->rank;
                //structural info
                p->x_idx = x_idx;
                p->y_idx = y_idx;
                p->dydx = dydx;
                //block info
                p->block_idx = our_dag->block_idx;
                p->s_idx = s_idx;
                p->e_idx = e_idx;

                buffer.push_back(*p);

                delete p;
            }
          }

          MPI_Isend( &buffer[0] , buffer.size() , MPI_PARTIAL , 0 , DAG_MERG_REQ ,   MPI_COMM_WORLD , &mpireq );    
    }
Run Code Online (Sandbox Code Playgroud)

这里有人对这个错误有任何想法吗?

干杯。

Hri*_*iev 5

MPI 允许在对和 的调用中使用空请求句柄MPI_REQUEST_NULL(不要与 C/C++NULL指针混淆)。每当向 传递空请求句柄时,调用立即返回空状态,即状态对象的字段设置如下:MPI_WaitMPI_TestMPI_Wait

.MPI_TAG = MPI_ANY_TAG
.MPI_SOURCE = MPI_ANY_SOURCE
.MPI_ERROR = MPI_SUCCESS
Run Code Online (Sandbox Code Playgroud)

无论提供什么数据类型,以空状态调用MPI_Get_countMPI_Get_elements始终返回 0。每当向 传递空请求句柄时MPI_Test,调用会立即返回空状态,并且完成标志设置为true

双方MPI_WaitMPI_Test设置完成操作的要求,办理MPI_REQUEST_NULL。允许无错误地传递空句柄允许重复调用具有相同句柄变量的任何等待/测试函数而不会产生任何不良影响:

.MPI_TAG = MPI_ANY_TAG
.MPI_SOURCE = MPI_ANY_SOURCE
.MPI_ERROR = MPI_SUCCESS
Run Code Online (Sandbox Code Playgroud)

因此,对于这个问题中的情况,MPI_REQUEST_NULL在构造函数中设置(初始化)请求变量就足够了。第一次调用函数不需要特殊测试,代码的第一个版本将按预期工作。