私のアプリケーションでは、インフィニバンドインフラストラクチャを使用して、サーバーから別のサーバーにデータのストリームを送信します。私はソケットプログラミングに精通しているので、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
誰かが私が間違っていることを知っていますか?または私が改善できることは何ですか?私は「ここで発明されていない」症候群の影響を受けていないので、今までやってきたことを捨てて、何か他のものを採用することさえできます。ポイントツーポイントの連続転送のみが必要です。