[Users] infiniband rdma poor transfer bw

Gaetano Mendola mendola at gmail.com
Thu Aug 23 15:51:05 PDT 2012


Hi all,
I'm sorry in advance if this is not the right mailing list for my question.

In my application I use an infiniband infrastructure to send a stream
of data from a server to
another one. I have used to easy the development ip over infiniband
because I'm more familiar
with socket programming. Until now the performance (max bw) was good
enough for me (I knew
I wasn't getting the maximum bandwith achievable), now I need to get
out from that infiniband
connection more bandwidth.

ib_write_bw claims that my max achievable bandwidth is around 1500
MB/s (I'm not getting
3000MB/s because my card is installed in a PCI 2.0 8x).

So far so good. I coded my communication channel using ibverbs and
rdma but I'm getting far
less than the bandwith I can get, I'm even getting a bit less
bandwidth than using socket but
at least my application doesn't use any CPU power:

ib_write_bw: 1500 MB/s

sockets: 700 MB/s <= One core of my system is at 100% during this test

ibvers+rdma: 600 MB/s <= No CPU is used at all during this test

It seems that the bottleneck is here:

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");
}

at this point the next code waiting for completation that is:

//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";
}


The time from my ibv_post_send and when ibv_get_cq_event returns an
event is 13.3ms when transfering chuncks of 8 MB achieving then around 600 MB/s.

To specify more (in pseudocode what I do globally):

Active Side:

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

Passive Side:

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

Does anyone knows what I'm doing wrong? Or what I can improve? I'm not
affected by
"Not Invented Here" syndrome so I'm even open to throw away what I
have done until
now and adopting something else.

I only need a point to point contiguous transfer.


Regards
Gaetano Mendola


--
cpp-today.blogspot.com



More information about the Users mailing list