0

对于下面的代码,我想问几个问题(主要是问题 2),其目的是将数据发送到任意数量的“目标”等级,然后从所有目标接收其他数据(不同长度),即交换包含所有目标的数据。我不知道每个级别的数据发送和接收呼叫的顺序!每个消息的大小都很小(最多说 1MB),目标的数量可能多达 10 个。该应用程序是超级计算机上的高性能计算。

我的具体问题是为了确保我完全理解正在发生的事情(在网上任何地方都找不到特别提到的内容,这似乎很明显,但我想 100% 确定它总是有效的):

  1. 您能否确认 Bsend 和接收调用顺序永远不会导致任何死锁:我假设一旦所有要发送的消息都在缓冲区中,那么 MPI 可以轻松捕获任何目标接收调用并开始发送相关的缓冲发送数据,无论目标接收呼叫的顺序如何。那是对的吗?

2.如果每个等级有两个目标邻居(一个“左”和一个“右”),此代码是否会导致级联等待彼此的“左”邻居与自己的“左”邻居交换数据(这将导致性能非常差),或者即使排名正在等待接收调用,是否会发送要发送的缓冲数据?换句话说:一旦 Bsend 返回并缓冲了数据,实际的网络数据交换是否由 MPI 创建的另一个进程/线程执行?(可能是愚蠢的问题,这是我在 Bsend 返回后看到它发生的唯一方法)

  1. 有没有更好的方法来进行数据交换或者代码在速度方面看起来不错?在我的情况下,数据复制(即缓冲)本身不应导致可见的开销。

  2. 您会建议使用相同的代码与每个目标共享消息的大小(一个整数)还是有更快的方法?或者有什么办法可以避免发送消息大小的需要(在调用时是未知的)。

{

void slmpi::exchange(std::vector targetranks, std::vector sendlens, std::vector<int*> sendbuffers, std::vector receivelens, std::vector<int*> receivebuffers)

int numtargets = targetranks.size();

if (numtargets == 0)
    return;

int totbytelen = 0;
for (int i = 0; i < numtargets; i++)
    totbytelen += sendlens[i]*sizeof(int) + MPI_BSEND_OVERHEAD;

std::vector<char> sendbuffer(totbytelen); // a char is one byte long
MPI_Buffer_attach(&sendbuffer[0], totbytelen);
 
for (int i = 0; i < numtargets; i++)
    MPI_Bsend(sendbuffers[i], sendlens[i], MPI_INT, targetranks[i], 0, MPI_COMM_WORLD);
 
for (int i = 0; i < numtargets; i++)
    MPI_Recv(receivebuffers[i], receivelens[i], MPI_INT, targetranks[i], 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
 
MPI_Buffer_detach(&sendbuffer[0], &totbytelen);

}

4

0 回答 0