按值返回MPI_Request和MPI_Status对象是否危险?

时间:2017-06-26 14:22:12

标签: c++ parameters mpi

我正在用C ++编写一个用于MPI的光包装器。为了使事情更容易,我有一些函数返回一个MPI_Request对象而不是一个作为指针。代码在我的计算机上工作正常,但我担心它可能会导致MPI的不同实现出现问题。

下面是一些示例代码:

template<class T> MPI_Request ireceive(T* data, int count, int source, int tag)
{
    MPI_Request request;
    MPI_Irecv(data, get_mpi_type<T>::mul * count, get_mpi_type<T>::type(), source, tag, MPI_COMM_WORLD, &request);
    return request;
}
template<class T> MPI_Request ireceive(std::vector<T>& dest, int source, int tag)
{
    MPI_Status status = probe(source, tag);
    int size = get_msg_size<T>(status);
    dest.clear();
    dest.resize(size);
    return ireceive(&dest[0], size, source, tag, status);
}
MPI_Status wait(MPI_Request& request)
{
    MPI_Status status;
    MPI_Wait(&request, &status);
    return status;
}
MPI_Status test(MPI_Request& request, int& flag)
{
    MPI_Status status;
    MPI_Test(&request, &flag, &status);
    return status;
}

前两个函数直接返回一个MPI_Request对象,后两个函数返回一个MPI_Status对象。我担心,在另一个MPI实现中,这些函数可能会导致未定义的行为。

按值返回MPI_Request和MPI_Status对象是否危险?

2 个答案:

答案 0 :(得分:2)

  

按值返回MPI_Request和MPI_Status对象是否危险?

可能会导致错误,如answer中所述。

  

会影响表现吗?

这些结构不应该大到足以降低性能,但一般来说,当通过引用传递是一种选择时,应该遵循它。

答案 1 :(得分:2)

MPI_Status结构基本上是一个整数数组,用于报告特定通信的结果,无论是点对点接收还是非阻塞操作。复制此结构并不危险,您可以使用作业或memcpy来完成。复制它的性能损失应该不是问题,因为这些元素的典型大小约为20字节(MPI 3.1)。

另一方面,MPI_Request并非无足轻重。我还在C ++中为一个项目制作了一些MPI包装器(因为C ++ API已被弃用,并且在各个实现中不一致)。 MPI_Request结构基本上是句柄(将其看作指针),用于检查操作的完成状态。如果释放句柄(因为非阻塞操作已完成,或者您调用了MPI_Request_freeMPI_Cancel,则该对象不再有效,并且MPI_Request句柄设置为{ {1}}。

根据我的经验,MPI_REQUEST_NULL包装类最好是不可复制的。您仍然可以使用引用或指针共享它们。这样可以节省一些调试时间。

参见MPI标准文件3.1,第3.7节“非阻塞通信”

  

如果请求标识的操作完成,则对MPI_Request的调用将返回MPI_TEST。在这种情况下,状态对象被设置为包含关于已完成操作的信息。如果请求是活动持久请求,则将其标记为非活动。 取消分配任何其他类型的请求,请求句柄设置为flag = true。 [...]

     

允许一个使用null或inactive请求参数调用MPI_REQUEST_NULL。在这种情况下,操作将返回MPI_TEST并为空状态。

注意:null或非活动请求不是无效的请求句柄,例如,它是释放flag = true并仅将其中一个副本设置为MPI_Request的结果。