首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RDMA程序随机挂起

RDMA程序随机挂起
EN

Stack Overflow用户
提问于 2015-08-07 19:04:44
回答 1查看 570关注 0票数 2

有没有人用过RDMA_CM库做过远程直接存储器存取编程?

我很难找到简单的例子来研究。在librdmacm中有一个rdma_client & rdma_server示例,但它不会在循环中运行(rping确实会循环,但它是直接使用IB动词而不是rdma_cm函数编写的)。

我编写了一个简单的乒乓球程序,但它在1- 100次弹跳后在任何地方都会锁定。我发现在客户端中添加睡眠会使它在挂起之前工作更长时间,这表明存在竞争条件。

客户机卡在rdma_get_send_comp()中,服务器卡在rdma_get_recv_comp()中。

我有限的理解是,在每次rdma_post_send()之前,您需要发出一个在发送之后的rdma_post_recv()。同样,在每次发送之前(除了第一次客户端发送之外),您需要等待一条消息(rdma_get_recv()),指示另一端已准备好接收。

会出什么问题呢?

代码语言:javascript
复制
Server(rdma_cm_id *id)
{
    ibv_wc wc;

    int ret;
    uint8_t recvBuffer[MESSAGE_BUFFER_SIZE],
            sendBuffer[MESSAGE_BUFFER_SIZE];

    ibv_mr *recvMemRegion =  rdma_reg_msgs(id, recvBuffer, MESSAGE_BUFFER_SIZE);
    if (!recvMemRegion)
      throw 0;

    ibv_mr *sendMemRegion = rdma_reg_msgs(id, sendBuffer, MESSAGE_BUFFER_SIZE);
    if (!sendMemRegion)
      throw 0;


    if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
      throw 0;


    if (ret = rdma_accept(id, NULL))
       throw 0;

    do
    {
        if ((ret = rdma_get_recv_comp(id, &wc)) <= 0)
            throw 0;

        if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
          throw 0;

        if (ret = rdma_post_send(id, NULL, sendBuffer, 1, sendMemRegion, 0))
           throw 0;

        printf(".");
        fflush(stdout);

        if ((ret = rdma_get_send_comp(id, &wc)) <= 0)
          throw 0;
    }
    while (true);
}

Client()   // sends the 1st message
{
    // queue-pair parameters are:
    attr.cap.max_send_wr = attr.cap.max_recv_wr = 4;
    attr.cap.max_send_sge = attr.cap.max_recv_sge = 2;
    attr.cap.max_inline_data = 16;
    attr.qp_context = id;
    attr.sq_sig_all = 1;
    attr.qp_type = IBV_QPT_RC;

    <create connection boiler plate>

    uint8_t recvBuffer[MESSAGE_BUFFER_SIZE],
            sendBuffer[MESSAGE_BUFFER_SIZE];

    recvMemRegion = rdma_reg_msgs(id, recvBuffer, MESSAGE_BUFFER_SIZE);
    if (!recvMemRegion)
        throw 0;

    sendMemRegion = rdma_reg_msgs(id, sendBuffer, MESSAGE_BUFFER_SIZE);
    if (!sendMemRegion)
        throw 0;

    if (ret = rdma_connect(id, NULL))
      throw 0;

    do
    {
        if (ret = rdma_post_recv(id, NULL, recvBuffer, 1, recvMemRegion))
          throw 0;

        //usleep(5000);
        if (ret = rdma_post_send(id, NULL, sendBuffer, 1, sendMemRegion, 0))
          throw 0;

        if ((ret = rdma_get_send_comp(id, &wc)) <= 0)
           throw 0;

        if ((ret = rdma_get_recv_comp(id, &wc)) <= 0)
          throw 0;

        printf(".");
        fflush(stdout);
    } 
    while (true);
}
EN

回答 1

Stack Overflow用户

发布于 2015-08-08 17:36:25

诅咒!我被SUSE 11附带的librdmacm-1.0.15-1 (来自2012)中的一个bug咬了一口,我知道我的send/recv序列没有问题。

我首先尝试将我的代码与其他示例进行比较。在一个例子中,我看到

代码语言:javascript
复制
while (!ibv_poll_cq(id->send_cq, 1, &wc));

而不是rdma_get_send_comp(),rdma_get_recv_comp()也是如此。我尝试替换我的示例中的那些,奇迹般地,挂起的东西消失了!

嗯,也许rdma_get_send_comp()没有做我期望的事情。我最好先看一下代码。我得到了1.0.15和1.0.18的代码,我在rdma_verbs.h中看到了什么?

两个截然不同的IB动词序列:

代码语言:javascript
复制
// 1.0.15
rdma_get_send_comp(struct rdma_cm_id *id, struct ibv_wc *wc)
{
        struct ibv_cq *cq;
        void *context;
        int ret;

        ret = ibv_poll_cq(id->send_cq, 1, wc);
        if (ret)
                goto out;

        ret = ibv_req_notify_cq(id->send_cq, 0);
        if (ret)
                return rdma_seterrno(ret);

        while (!(ret = ibv_poll_cq(id->send_cq, 1, wc))) {
                ret = ibv_get_cq_event(id->send_cq_channel, &cq, &context);
                if (ret)
                        return rdma_seterrno(ret);

                assert(cq == id->send_cq && context == id);
                ibv_ack_cq_events(id->send_cq, 1);
        }
out:
        return (ret < 0) ? rdma_seterrno(ret) : ret;
}

vs
// 1.0.18
rdma_get_send_comp(struct rdma_cm_id *id, struct ibv_wc *wc)
{
        struct ibv_cq *cq;
        void *context;
        int ret;

        do {
                ret = ibv_poll_cq(id->send_cq, 1, wc);
                if (ret)
                        break;

                ret = ibv_req_notify_cq(id->send_cq, 0);
                if (ret)
                        return rdma_seterrno(ret);

                ret = ibv_poll_cq(id->send_cq, 1, wc);
                if (ret)
                        break;

                ret = ibv_get_cq_event(id->send_cq_channel, &cq, &context);
                if (ret)
                        return ret;

                assert(cq == id->send_cq && context == id);
                ibv_ack_cq_events(id->send_cq, 1);
        } while (1);

        return (ret < 0) ? rdma_seterrno(ret) : ret;
}

谁能解释为什么1.0.18工作,而1.0.15随机挂起?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31876197

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档