5

私のアプリケーションでは、インフィニバンドインフラストラクチャを使用して、サーバーから別のサーバーにデータのストリームを送信します。私はソケットプログラミングに精通しているので、infinibandを介して開発IPを簡単に使用していました。これまで、パフォーマンス(max bw)は私にとって十分でした(達成可能な最大帯域幅が得られていないことはわかっていました)が、今はその無限帯域幅接続からより多くの帯域幅を取得する必要があります。

ib_write_bwは、達成可能な最大帯域幅が約1500 MB / sであると主張しています(カードがPCI 2.0 8xにインストールされているため、3000MB / sを取得していません)。

ここまでは順調ですね。ibverbsとrdmaを使用して通信チャネルをコーディングしましたが、取得できる帯域幅よりもはるかに少なくなっています。ソケットを使用するよりも帯域幅が少し少なくなっていますが、少なくともアプリケーションはCPUパワーを使用していません。

ib_write_bw:1500 MB / s

ソケット:700 MB / s <=このテスト中、システムの1つのコアは100%です。

ibvers + rdma:600 MB /s<=このテストではCPUはまったく使用されません

ボトルネックはここにあるようです:

ibv_sge sge;
sge.addr = (uintptr_t)memory_to_transfer;
sge.length = memory_to_transfer_size;
sge.lkey = memory_to_transfer_mr->lkey;

ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.wr_id = 0;
wr.opcode = IBV_WR_RDMA_WRITE;
wr.sg_list = &sge;
wr.num_sge = 1;
wr.send_flags = IBV_SEND_SIGNALED;
wr.wr.rdma.remote_addr = (uintptr_t)thePeerMemoryRegion.addr;
wr.wr.rdma.rkey = thePeerMemoryRegion.rkey;

ibv_send_wr *bad_wr = NULL;
if (ibv_post_send(theCommunicationIdentifier->qp, &wr, &bad_wr) != 0) {
  notifyError("Unable to ibv post receive");
}

この時点で、完了を待機している次のコードは次のとおりです。

//Wait for completation
ibv_cq *cq;
void* cq_context;
if (ibv_get_cq_event(theCompletionEventChannel, &cq, &cq_context) != 0) {
  notifyError("Unable to get a ibv cq event");
}

ibv_ack_cq_events(cq, 1);

if (ibv_req_notify_cq(cq, 0) != 0) {
  notifyError("Unable to get a req notify");
}

ibv_wc wc;
int myRet = ibv_poll_cq(cq, 1, &wc);
if (myRet > 1) {
  LOG(WARNING) << "Got more than a single ibv_wc, expecting one";
}

私のibv_post_sendからibv_get_cq_eventがイベントを返すまでの時間は、8MBのチャンクを転送して約600MB/sを達成したときに13.3msです。

さらに指定するには(疑似コードでグローバルに行うこと):

アクティブサイド:

post a message receive
rdma connection
wait for rdma connection event
<<at this point transfer tx flow starts>>
start:
register memory containing bytes to transfer
wait remote memory region addr/key ( I wait for a ibv_wc)
send data with ibv_post_send
post a message receive
wait for ibv_post_send event ( I wait for a ibv_wc) (this lasts 13.3 ms)
send message "DONE"
unregister memory 
goto start

パッシブサイド:

post a message receive
rdma accept
wait for rdma connection event
<<at this point transfer rx flow starts>>
start:
register memory that has to receive the bytes
send addr/key of memory registered
wait "DONE" message 
unregister memory
post a message receive
goto start

誰かが私が間違っていることを知っていますか?または私が改善できることは何ですか?私は「ここで発明されていない」症候群の影響を受けていないので、今までやってきたことを捨てて、何か他のものを採用することさえできます。ポイントツーポイントの連続転送のみが必要です。

4

2 に答える 2

4

擬似コードに基づいて、転送ごとにメモリ領域を登録および登録解除するように見えます。それがおそらく物事が遅い主な理由だと思います。メモリ登録はかなりコストのかかる操作なので、できるだけ少なくして、メモリ領域をできるだけ再利用したいと思います。メモリの登録に費やされる時間はすべて、データの転送に費やさない時間です。

これは、擬似コードの2番目の問題を示しています。同期的に完了を待機しており、前の作業要求が完了するまで別の作業要求を投稿しません。つまり、作業要求が完了してから完了を取得して別の要求を投稿するまでの間、HCAはアイドル状態です。複数の送信/受信作業要求を処理し続けることをお勧めします。これにより、HCAが1つの作業要求を完了すると、すぐに次の作業要求に進むことができます。

于 2012-08-24T17:06:47.077 に答える
2

ページサイズに合わせて送信するバッファを割り当てる問題を解決しました。私のシステムでは、ページサイズは4K(sysconf(_SC_PAGESIZE)によって返される値)です。そうすることで、(まだ登録/登録解除を行っていますが)約1400MB/秒に到達することができます。

于 2012-08-29T18:20:16.960 に答える