std :: vector作为MPI非阻塞函数的输入缓冲区

时间:2018-02-02 20:27:01

标签: c++ vector mpi

TLDR :如果您对非阻塞MPI点对点或RMA函数的输入缓冲区是向量,那么在某些时候,指向底层元素的指针将无效(插入向量时),从而导致如果通信操作不完整,则会出现内存损坏问题。

考虑这个函数,我必须将输入数据复制到向量中,然后将其传递给MPI_Issend(或任何非阻塞发送):

    void TaggedIssend(int tag, int target, int count, const long* data)
    {
        // data
        const long msgq_size = msgQ_data_.size();
        for (int i = 0; i < count; i++)
            msgQ_data_.push_back(data[i]);

        // request
        const long req_size = msgQ_reqs_.size();
        msgQ_reqs_.push_back(MPI_REQUEST_NULL);

        MPI_Issend(&msgQ_data_[msgq_size], count, MPI_LONG, 
                target, tag, comm_, &msgQ_reqs_[req_size]);
    }

在某一时刻,msgQ_data_msgQ_reqs_将被移动(复制到新位置),此时如果发送未完成,则程序将崩溃(将出现段错误在看似奇怪的地方,MPI_Request对象可能会在测试时变得无效,仅举几个问题)。虽然我在这个特定问题中使用std::vector,但在动态调整数组大小时会出现相同的问题。这就是为什么MPI通信功能的输入缓冲区类型为const void*

问题:我有兴趣了解安全使用动态调整大小数组作为MPI非阻塞函数的输入缓冲区的技巧。我目前正在将传出数据推送到固定大小的缓冲区,当它已满时,我一次发出所有发送,并在重新使用缓冲区之前完成它们。谁能提出更好的选择? 我在这里使用MPI_Issend的原因是因为我的发送发生在while循环中,我可以测试所有发送通信完成(测试与MPI_Issend相关的请求将仅在以下情况下返回true匹配接收已发布),并使​​用它来摆脱循环。

1 个答案:

答案 0 :(得分:1)

  

我很想知道安全使用动态调整大小数组作为MPI非阻塞函数的输入缓冲区的技术。

使用std::vector::reserve分配足够的内存空间。然后,如果您push_back进入vector,则保证在保留容量未满之前不会重新分配。这个解决方案有点脆弱,但如果事先知道最大矢量大小,它就会起作用。

或者,您也可以使用MPI_Bsend发送,例如,使用某个递增的tag参数,然后再发送此标记以测试是否已收到数据。