请求事件是一种机制,请求方发送消息,当响应方收到消息时,响应方会生成特殊(即请求的)事件。当工作完成添加到响应方(在接收队列中)的完成队列时,将为消息生成事件,因此它仅对发送(SEND)、立即发送(Send with immediate)和 RDMA 立即写入(Write with immediate)操作有效(因为只有这些操作会在响应方生成工作完成)
如果希望降低 CPU 消耗,并且不想使用常规频繁的工作完成事件,即下一个工作完成时,接收方总是将WQE添加到完成队列, 而是发送方将其标记为“特殊”的工作完成,那么请求事件机制就是答案
使用请求事件可以帮助减少接收方的 CPU 消耗,因为它可以休眠直到收到带有请求事件的消息(即来自发送方的“提示”)。与每次收到消息时唤醒并检查特定条件相比(即处理的事件更少)。
一般SE配合CQ中断模式使用
发送方调用ibv_post_send()时,需要在 send_wr.send_flags 中设置IBV_SEND_SOLICITED标记位。注意: 这仅与上面提到的操作相关
如UCX中的零拷贝发送(uct_rc_verbs_ep_am_zcopy):
ucs_status_t do_am_zcopy -> 零拷贝
ucs_status_t uct_rc_verbs_ep_am_zcopy(uct_ep_h tl_ep, uint8_t id, const void *header,
unsigned header_length, const uct_iov_t *iov,
size_t iovcnt, unsigned flags,
uct_completion_t *comp)
{
uct_rc_verbs_iface_t *iface = ucs_derived_of(tl_ep->iface, uct_rc_verbs_iface_t);
uct_rc_verbs_ep_t *ep = ucs_derived_of(tl_ep, uct_rc_verbs_ep_t);
uct_rc_iface_send_desc_t *desc = NULL;
struct ibv_sge sge[UCT_IB_MAX_IOV]; /* First sge is reserved for the header */
struct ibv_send_wr wr;
int send_flags;
size_t sge_cnt;
/* 1 iov consumed by am header */
UCT_CHECK_IOV_SIZE(iovcnt, iface->config.max_send_sge - 1,
"uct_rc_verbs_ep_am_zcopy");
UCT_RC_CHECK_AM_ZCOPY(id, header_length, uct_iov_total_length(iov, iovcnt),
iface->config.short_desc_size,
iface->super.super.config.seg_size);
UCT_RC_CHECK_RES_AND_FC(&iface->super, &ep->super, id);
UCT_RC_IFACE_GET_TX_AM_ZCOPY_DESC(&iface->super, &iface->short_desc_mp,
desc, id, header, header_length, comp,
&send_flags);
sge[0].length = sizeof(uct_rc_hdr_t) + header_length;
sge_cnt = uct_ib_verbs_sge_fill_iov(sge + 1, iov, iovcnt);
UCT_RC_VERBS_FILL_AM_ZCOPY_WR_IOV(wr, sge, (sge_cnt + 1), wr.opcode);
UCT_TL_EP_STAT_OP(&ep->super.super, AM, ZCOPY,
(header_length + uct_iov_total_length(iov, iovcnt)));
// 发送方设置请求事件标记
uct_rc_verbs_ep_post_send_desc(ep, &wr, desc, send_flags | IBV_SEND_SOLICITED,
UCT_IB_MAX_ZCOPY_LOG_SGE(&iface->super.super));
UCT_RC_UPDATE_FC(&ep->super, id);
return UCS_INPROGRESS;
}
应该在接收完成队列上调用ibv_req_notify_cq() ,该队列可能会收到带有 Solicited 事件的传入消息; 且solicited_only参数值应该非零。
该还函数参数和实现如下:
请求 CQ 上的完成通知。当条目添加到 CQ 时,将向与 CQ 关联的完成通道(completion channel)添加事件。
@cq:请求通知的完成队列。
@solicited_only:如果非零,则仅为下一个请求事件完成(SE),生成CQ事件。如果为零,则任何 CQ 条目(无论是否请求)都将生成事件 (Notifies only if the WR is flagged as solicited)
static inline int ibv_req_notify_cq(struct ibv_cq *cq, int solicited_only)
{
return cq->context->ops.req_notify_cq(cq, solicited_only);
}
这将导致ibv_get_cq_event()被阻塞,直到发生下列情况之一:
概括为一句话: A facility by which a message sender may cause an event to be generated at the recipient when the message is received
在基本传输头BTH中的SE
一般在创建CQ时会设置事件处理程序
创建CQ时设置回调函数
static int create_cq
...
cq->comp_handler = ib_uverbs_comp_handler;
cq->event_handler = ib_uverbs_cq_event_handler;
...
static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)
...
cq->comp_handler = ib_uverbs_comp_handler;
cq->event_handler = ib_uverbs_cq_event_handler;
...
11.4.2.2 请求完成通知
描述:当指定类型的下一个完成条目添加到指定 CQ 时,请求调用 CQ 事件处理程序。对于特定的 CQ,每次请求完成通知调用时,处理程序最多调用一次。在启用通知之前存在的任何 CQ 条目都不会导致调用处理程序, 完成事件有两种类型:请求的或未经请求的。当传入的发送或 RDMA 写入即时数据消息(设置了请求的事件标头位)导致成功的接收工作完成添加到 CQ 时,或者当不成功的工作完成添加到 CQ 时,会发生请求的完成事件。当任何其他成功的接收工作完成或任何成功的发送工作完成添加到 CQ 时,会发生未经请求的完成事件。
C11-29:CI 应支持请求的和未经请求的完成事件类型。消费者请求完成通知时,必须指定是否为以下事件调用通知回调:
• 仅限下一个请求的完成事件,或
• 下一个请求或非请求的完成事件。
C11-29.1.1:当“仅限下一个请求的完成事件”未完成时,CI 应在以下任一情况下调用通知回调:
• 设置了请求的事件标头位的传入发送导致成功的接收工作完成被添加到指定的 CQ。
• 设置了请求的事件标头位的传入 RDMA 写入和立即数据导致成功的接收工作完成被添加到指定的 CQ。
• 将不成功的发送或接收工作完成添加到指定的 CQ。
C11-29.1.2:当“下一个请求或非请求的完成事件”未完成时,CI 应在将任何工作完成添加到指定的 CQ 时调用通知回调。如果请求完成通知处于待处理状态,则在完成事件之前对同一 CQ 的请求完成通知的后续调用仅在通知发生时才会生效。下一个完成事件的请求完成通知优先于同一 CQ 的请求事件完成的请求完成通知。如果对同一 CQ 进行了多次请求完成通知调用,并且至少有一个请求将类型设置为下一个完成,则在将下一个完成添加到该 CQ 时将调用 CQ 事件处理程序。即使在指定 CQ 的完成事件之前进行了多个 CQ 通知请求,CQ 事件处理程序也只会被调用一次。一旦调用 CQ 事件处理程序,必须先注册另一个完成通知请求,然后才能再次调用 CQ 事件处理程序。
C11-30:当 CQ 上请求的完成类型的完成通知请求未完成,并且对该 CQ 进行了另一个指定下一个完成通知的请求时,CI 应将未完成的完成通知类型更改为下一个完成。
C11-31:当 CQ 上下一个完成的完成通知请求未完成,并且对该 CQ 发出了另一个通知请求时,CI 不得更改未完成的完成通知类型。在调用此例程之前,必须指定 CQ 事件处理程序。如果在生成事件时尚未注册 CQ 事件处理程序,则不会进行处理程序调用。调用 CQ 事件处理程序时,它仅表示已将新条目添加到指定的 CQ。HCA 和 CQ 句柄被传递给 CQ 事件处理程序,因此 CQ 事件处理程序可以确定哪个 CQ 导致它被调用。调用处理程序例程后,消费者必须再次调用请求完成通知,以便在向该 CQ 添加新条目时收到通知。消费者有责任调用轮询完成动词来检索工作完成。注意:如果消费者在没有与 CQ 关联的 CQ 事件处理程序 ID 的 CQ 句柄上请求完成通知,则该操作将不起作用。也就是说,不会生成任何完成事件。
输入修饰符:
• HCA 句柄。
• CQ 句柄。
• 请求的完成通知类型。类型是下一个完成或请求的完成发生时。
输出修饰符:
动词结果:
• 操作已成功完成。
• 无效的 HCA 句柄。
• 无效的 CQ 句柄。
• 无效的完成通知类型
A4.11.2 请求事件
SDP 实现的SE功能, 偶尔需要停止半连接上的处理并等待以下消息之一到达后再继续:
RDMAmojo-SE: https://www.rdmamojo.com/2014/05/27/solicited-event/
IBM_ibv_req_notify_cq: https://www.ibm.com/docs/en/aix/7.1?topic=management-ibv-req-notify-cq
IB_SPEC
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。