Что такое индекс источника (PI) в контексте ibv_exp_post_send и ibv_exp_post_task?

Я пытаюсь использовать поддержку многоканальной связи, описанную в Приложении D к Руководству пользователя по программированию RDMA. К сожалению, я немного смущен значениями некоторых аргументов функций.

Мой вопрос

ibv_exp_post_send() а также ibv_exp_post_task() функции принимают связанный список структур рабочих запросов и набор * структур рабочих запросов соответственно. Что означают cq_count и wqe_count в этой структуре?

struct ibv_exp_send_wr {
  // ...
  union {
    // ...          
    struct {
      struct ibv_cq   *cq; /* Completion queue (CQ) that WAIT WR relates to */
      int32_t  cq_count;   /* Producer index (PI) of the CQ */
    } cqe_wait; /* Describes IBV_EXP_WR_CQE_WAIT WR */
    struct {
      struct ibv_qp   *qp; /* Queue pair (QP) that SEND_EN/RECV_EN WR relates to */
      int32_t  wqe_count; /* Producer index (PI) of the QP */
    } wqe_enable; /* Desribes IBV_EXP_WR_RECV_ENABLE and IBV_EXP_WR_SEND_ENABLE WR */
  } task;
  // ...
};

Всегда ли первый рабочий запрос / завершение имеет номер 1, а последующие линейно увеличиваются? Или это иногда сбрасывается, как между вызовами ibv_exp_post_task(), или уменьшается после обработки некоторых запросов? Соответствуют ли числа между ibv_exp_post_send или ibv_exp_post_task?

* Технически, указатель на связанный список задач, каждая из которых содержит связанный список рабочих запросов.

1 ответ

Решение

Насколько я вижу, cq_count Значение поля зависит от флага, который может быть установлен в ibv_exp_send_wr.send_flags: IBV_EXP_SEND_WAIT_EN_LAST,

Если этот флаг очищен, cq_count определяет относительное смещение завершения, которое нужно ждать. Смещение относительно внутреннего поля для каждого CQ, которое обновляется, только когда установлен флаг.

Проверьте этот код из драйвера libmlx5:

case IBV_EXP_WR_CQE_WAIT:
{
        struct mlx5_cq *wait_cq = to_mcq(wr->task.cqe_wait.cq);
        uint32_t wait_index = 0;

        wait_index = wait_cq->wait_index +
                        wr->task.cqe_wait.cq_count;
        wait_cq->wait_count = max(wait_cq->wait_count,
                        wr->task.cqe_wait.cq_count);

        if (exp_send_flags & IBV_EXP_SEND_WAIT_EN_LAST) {
                wait_cq->wait_index += wait_cq->wait_count;
                wait_cq->wait_count = 0;
        }

        set_wait_en_seg(seg, wait_cq->cqn, wait_index);
        seg   += sizeof(struct mlx5_wqe_wait_en_seg);
        size += sizeof(struct mlx5_wqe_wait_en_seg) / 16;
}
break;

wqe_count ведет себя аналогично, за исключением того, что он также может принимать специальное значение ноль, запрашивая драйвер включить все ранее опубликованные рабочие запросы.

Другие вопросы по тегам