【RDMA】使用‘无信号完成’(Working with Unsignaled completions)|IBV_SEND_SIGNALED

目录

前言-术语

使用‘静默完成’(Working with Unsignaled completions)

什么是'静默完成'?What is Unsignaled Completion?

为什么要使用'静默完成'?Why use Unsignaled Completion?

何时使用'静默完成'?When to use Unsignaled Completion?

如何使用'静默完成'?How to use Unsignaled Completion?

陷阱和隐患Gotchas and Pitfalls

例子

常见问题 

IBV_SEND_SIGNALED


前言-术语

Unsignaled completion = ‘无信号完成’='静默完成'

Work Requests            = '工作请求'  = WR

Work Completion         = '工作完成'  = WC

Send Request             = '发送请求'  = SR

Receive Requests      = '接收请求' = RR

Send Queue              = ‘发送队列’ =SQ

@UESTC

请求者完成一个verb 操作后,请求者的NIC可以通过DMA将完成条目(CQE)添加到(对端)的CQ(与对应QP相关联的CQ)。也可以通过在请求中设置标志不生成CQE,由应用程序自己的使用别的方法去检测到CQ。

使用‘无信号完成’(Working with Unsignaled completions)

原文:Working with Unsignaled completions - RDMAmojo RDMAmojo

默认情况下,所有'工作请求'WR在处理完成后都会生成'工作完成'WC。但是,当处理完成时,发送请求可能会也可能不会生成工作完成 - 这完全由应用程序控制,这称为静默完成( Unsignaled Completions)。在这篇文章中,我将介绍何时以及如何使用它。

什么是'无信号完成'?What is Unsignaled Completion?


Unsignaled Completion 是一种机制,允许应用程序发布'发送请求'SR,当它们的处理结束时,只要'工作完成'WC '工作请求'WR的处理没有出错,就不会(在与'发送队列'SQ相关联的'完成队列'CQ中)生成'工作完成'WC。但如果'发送请求'SR以错误结束,即使它被发布为使用静默完成(Unsignaled Completion),它也会生成一个工作完成WC。

(原文:Working with Unsignaled completions - RDMAmojo RDMAmojo

为什么要使用'无信号完成'?Why use Unsignaled Completion?


处理'工作请求'WR消耗机器的资源:

  • 由 RDMA 设备生成'工作完成'WC
  • 轮询(Polling )完成队列获取'工作完成'WC
  • 读取'工作完成'WC并检查其状态

处理较少的'工作完成'wc将有助于降低应用程序的 CPU 使用率,从而提高应用程序的效率并改善处理消息的延迟。

(使用Unsignaled completion告诉RDMA设备处理完不要生成WC?)

何时使用'无信号完成'?When to use Unsignaled Completion?

与消息到来(incoming messages)异步消耗'接收请求'RR(Receive Requests)而产生'工作完成'wc不同。

应用程序期望处理'发送请求'sr (处理)完结后产生'工作完成'wc  。此外,完结的'接收请求'RR产生的'工作完成'WC可能包含重要信息(操作码opcode、消息大小size、来源origin等),但完结的'发送请求'sr的'工作完成'wc不包含重要信息

(wr_id 的值,这是完全由应用程序控制。

在'发送请求'sr中可以指定的操作有两组:

  • 请求远程端发送数据的操作(RDMA Read 和 Atomic操作)
  • 将数据发送到远程端的操作(Send 和 RDMA Write-有或没有立即数据 immediate data)


如果满足以下所有条件,Unsignaled Completions 可用于第一组的操作:

  • 应用程序可以请求远程端读取多个缓冲区(在需要使用它们的内容之前)
  • 所有传入的数据都写入不同的内存缓冲区
  • 存放传入数据的内存区域不需要销毁/重用
  • The application can request the remote side to read several buffers before it needs to use their content
  • All incoming data is written to different memory buffers
  • The Memory Regions that contain the incoming data don't need to be destroyed/reused

如果满足以下所有条件,Unsignaled Completions 可用于第二组的操作:

  • 应用程序可以不需要逐个确认的连续发送多条消息。
  • 存放要发送的数据的内存区域不需要销毁/重用。(内存区域需要销毁/重用的,就应产生WC尽快把内存区的数据读出来,好把内存让给后面的应用)
  • 对于 UD QP,远程端的地址句柄(Address Handles )不需要销毁/重用
  • The application can send several messages before it needs acknowledge that there processing ended
  • The Memory Regions that contain the data to be sent don't need to be destroyed/reused
  • For UD QPs, Address Handles to the remote side don't need to be destroyed/reused

如何使用'无信号完成'?How to use Unsignaled Completion?

 对'静默完成'的支持是按 Queue Pair配置的。创建Queue Pair时,应将其创建为在'发送队列'中支持'静默完成'(属性 qp_init_attr.sq_sig_all 应设置为 0)。

 对于每个已发布的'发送请求'sr,如果在 wr.send_flags 中设置了标志 IBV_SEND_SIGNALED,则在该'发送请求'sr处理结束时将生成'工作完成'wc。如果清除此标志,则不会生成'工作完成'wc(只要它的完成没有错误)。

“Unsignaled的WR”意味着那些发送请求不会生成工作完成。
然而,他们仍然被认为是发送中的。 这意味着您需要不时通过发送signaled的SR来清空发送队列(否则,发送队列将满,您将无法发布任何新的SR)。

最重要的是,您必须不时发布signaled的发送请求SR
(如果发送队列大小为 N,您可以每 N 条消息发布signaled的发送请求,并且通过polling其WC,您将清空发送队列)。

ibv_post_send() - RDMAmojo RDMAmojo

陷阱和隐患Gotchas and Pitfalls

所有已发布的'发送请求'sr、有信号和无信号(静默)都被认为是未完成的,直到它们或在它们之后发布的'发送请求'sr 从与'发送队列'sq相关联的'完成队列'cq中轮询的'工作完成'wc为止。

(即只有把WC读出来,SR才算是完成了?)

(All posted Send Requested, Signaled and Unsignaled, are considered outstanding until a Work Completion that they, or Send Requests that were posted after them, was polled from the Completion Queue associated with the Send Queue. )

这意味着如果使用配置为使用'静默完成'(Unsignaled Completions)的Queue Pair,则必须确保偶尔的(在'发送队列'SQ充满未完成的'发送请求'SR之前)posted一个会生成WC的Send Request(IBV_SEND_SIGNALED派上用场了?)。不遵循此规则可能会导致'发送队列'SQ被'发送请求'SR灌满,那将不会生'成工作完成':

  • 发送队列已满,因此无法向其发送新的发送请求。无法发新的可产生WC的请求让它产生WC?
  • 发送队列不能清空,因为不能再生成'工作完成'(原因是没有'工作完成',如果有'工作完成',可以轮询它清空发送队列)

(The Send Queue can't be emptied, since no Work Completion can be generated anymore (the reason is that no Work Completion, that can generate Work Completion that polling it will empty the Send Queue, can be posted))

  • 所有发布的'发送请求'sr的状态都被认为是未知的

例子

1. 准备一个 QP init 属性,显式设置 Unsignaled Completions:

struct ibv_qp_init_attr init_attr = {
	.send_cq = cq,
	.recv_cq = cq,
	.cap     = {
		.max_send_wr = 10,
		.max_recv_wr = 10,
		.max_send_sge = 1,
		.max_recv_sge = 1
	},
	.qp_type    = IBV_QPT_RC,
	.sq_sig_all = 0
};

 2. 准备一个 QP init 属性,隐含设置为 Unsignaled Completions:

struct ibv_qp_init_attr init_attr = {
	.send_cq = cq,
	.recv_cq = cq,
	.cap     = {
		.max_send_wr = 10,
		.max_recv_wr = 10,
		.max_send_sge = 1,
		.max_recv_sge = 1
	},
	.qp_type    = IBV_QPT_RC
};

 3. 准备一个 QP init 属性,隐含设置为 Unsignaled Completions:

struct ibv_qp_init_attr init_attr;
 
memset(&init_attr, 0, sizeof(init_attr));
 
init_attr.send_cq = cq;
init_attr.recv_cq = cq;
init_attr.cap.max_send_wr = 10;
init_attr.cap.max_recv_wr = 10;
init_attr.cap.max_send_sge = 1;
init_attr.cap.max_recv_sge = 1;
init_attr.qp_type = IBV_QPT_RC;

 4. 下面的发送请求SR,其结束后在配置为支持'静默完成'的QP中产生一个WC:

struct ibv_send_wr wr = {
	.num_sge    = 0,
	.opcode     = IBV_WR_SEND,
	.send_flags = IBV_SEND_SIGNALED
};

 5. 下面的发送请求SR,其结束后不会在配置为支持'静默完成'的QP中产生一个WC:

struct ibv_send_wr wr = {
	.num_sge    = 0,
	.opcode     = IBV_WR_SEND,
	.send_flags = 0
};

常见问题 

我不小心用使用'静默完成'的SR填充了'发送队列'sq,我不能再向qp发送SR。我怎样才能从这种状态中恢复过来?
您无法从此状态恢复。您需要销毁这个队列对并创建一个新的。

IBV_SEND_SIGNALED

在远程直接内存访问技术中有两种消息发送的模式:允许待处理的发送模式不允许待处理的发送模式。

RDMA绕过内核,这样的设计带来的一个问题:如何在用户态提供相应内存的保护。

最简单的实现是使用 不允许待处理的发送模式。

这种模式下,网卡会标记(
ibv_send_signaled)每一条发出的消息。当发送出一条消息之后需要等待整个发送过程完成才能发送下一条消息。即先向网卡发送一个消息请求,在等待网卡完成相应消息内容的读取之后才能进行下一次消息请求的发送。

这种模式更为直观和容易理解。当一次消息发送完成之后,相应的内容(内存)已经被网卡读取完成,之后就可以被系统回收再利用。体现了良好的资源利用效率。

但这种模式的缺点在于对于连续的消息发送场景,系统在每次信息发送中都需要等待网卡读取完相应内容(后才能回收利用内存?)。因此降低了系统消息发送的吞吐量。

为提升发送性能,请求的发送会使用允许待处理的发送模式。rdma网卡会维护一个待处理消息的队列。当向网卡发送一个消息请求之后,如果待处理队列没有满,那么可以立即进行下一个消息请求的发送。当待处理队列出现满溢的情况,需要等待之前一个标记的发送请求被网卡处理。该模式会标记第一个以及待处理队列满溢之后的第一个消息请求。

相比于不允许待处理的发送模式下需要等待每一个发送请求完成,允许待处理请求的模式可以在接收发送请求的同时处理之前请求消息读取的操作。这种处理方式提高了发送请求的并行性,为系统带来了更高的吞吐量。但同时,由于允许待处理的发送模式模糊了消息发送完成的时间节点,仅在少数情况会去等待网卡读取完消息内容,在多数情况下消息发送出去后网卡还没有将相应的消息内容读取到。而在消息密集场景下,这种发送模式很容易导致在网卡还没有读取完消息内容之前新的消息内容就将旧的内容覆盖,造成“消息污染”。以及,如果为每个消息分配独立的内存空间,那么大量的消息请求将会带来庞大的内存开销,大大影响资源的利用率。

适用于远程直接内存访问的内存管理方法、系统及介质与流程_X技术

http://cache.baiducontent.com/c?m=rWcWkxFIA6D3snihZRtrFIsjzYrud7lNOfb6ap4a5MRz5TQEASFn8lXHu712yWnAKeYl1AznDbjLS3V_cwl-_dZtMNbGn014wp-BwusIguKh6wXUQc6zCju6cV2A8x0jeIiSkDh4CQ03hjgYREq7bFyl_xngyMFoCK9mC5MvIsq&p=c274c54ad48659f00be2962455&newp=9863c91892934ead2abe9b7c4b53d8304a02c70e3cc3864e1290c408d23f061d4862e8bf22251b05d5ce7e650aab4b58eaf6327523454df6cc8a871d81ede0&s=1d4c8b75d2e7beab&user=baidu&fm=sc&query=IBV%5FSEND%5FSIGNALED&qid=b01532700002b77a&p1=6

@uestc

posted on 2022-10-04 01:23  bdy  阅读(81)  评论(0编辑  收藏  举报

导航