任意の数の「ターゲット」ランクにデータを送信し、すべてのターゲットから (異なる長さの) 他のデータを受信することを目的とする以下のコードについて、いくつかの質問 (主に質問 2.) をしたいと思います。すべてのターゲットを含むデータ。各ランクのデータ送受信の順番がわからない!各メッセージのサイズはかなり小さく (最大で 1MB まで)、ターゲットの数は最大で 10 までです。アプリケーションは、スーパーコンピューターでの高性能コンピューティングです。
何が起こっているのかを完全に理解していることを確認するための私の具体的な質問 (オンラインのどこにも具体的に言及されているものを見つけることができませんでした。明らかなように思えるかもしれませんが、常に機能することを 100% 確認したいと思います):
- Bsend と receive の呼び出し順序によってデッドロックが発生しないことを確認していただけますか: 送信するすべてのメッセージがバッファに格納されると、MPI はターゲットの受信呼び出しを簡単にキャッチし、関連するバッファリングされた送信データの送信を開始できると想定しています。ターゲットの受信呼び出しの順序に関係なく。あれは正しいですか?
2.すべてのランクに 2 つのターゲット ネイバー (「左」および「右」) がある場合、このコードは、「左」ネイバーが互いに「左」ネイバーとデータを交換するのをカスケード待機する可能性があります (これは、または、ランクが受信呼び出しを待機している場合でも、送信するバッファリングされたデータが送信されますか? 言い換えると、Bsend が返されてデータがバッファリングされると、実際のネットワーク データ交換は MPI によって作成された別のプロセス/スレッドによって実行されるのでしょうか? (おそらくばかげた質問です。Bsend が戻った後にそれが起こるのを見ることができる唯一の方法です)
データ交換を行うためのより良い方法はありますか、またはコードは速度の点で優れているように見えますか? 私の場合、データのコピー (つまり、バッファリング) 自体が目に見えるオーバーヘッドにつながることはありません。
同じコードを使用してメッセージのサイズ (1 つの整数) を各ターゲットと共有することをお勧めしますか、それとももっと速い方法がありますか? または、メッセージサイズを送信する必要を回避する方法はありますか (呼び出し時には不明です)。
{
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);
}