RDMA Shared Receive Queue(四)

news2024/11/26 13:41:20

参考知乎文章《RDMA之Shared Receive Queue》:https://zhuanlan.zhihu.com/p/279904125

SRQ

SRQ全称为Shared Receive Queue,即共享接受队列。在QP中,SQ用于下发SEND/WRITE/READ等操作,而RQ只用于下发RECV操作,对于本端来说,只有QP接收到对端发过来的Send报文和带立即数的报文(少量)才会消耗RWQE(RQ中的Post Receive WR),在实际使用中,SEND/RECV操作通常都是用于传递控制信息,WRITE和READ才是进行大量远端内存读写操作时的主角,所以自然SQ的使用率是远远高于RQ的。

所以,协议为了给接收端节省资源而设计了SRQ,不同的QP使用一个特殊的RQ,这个特殊的RQ就是SRQ。当与其关联的QP想要下发接收WQE时,都填写到这个SRQ中,然后每当硬件接收到数据后,就根据SRQ中的下一个RWQE的内容把数据存放到指定位置。

例如下图所示,左侧未非共享RQ形态,右侧为共享SRQ形态。

  • 对于非共享RQ形态,当QP2接收到send报文,将从QO2的RQ中拿下一个RWQE处理,当QP3接收到send报文,将从QO3的RQ中拿下一个RWQE处理。
  • 对于共享SRQ形态,当QP2接收到send报文,将从SRQ中拿下一个RWQE处理,当QP3接收到send报文,也将从SRQ中拿下一个RWQE处理。
    在这里插入图片描述

为什用SRQ?(本小节参考知乎文章)

使用SRQ最大好处就是节省资源,先引用一下协议中关于使用SRQ的说明(协议1.4版本 10.2.9.1章节):

Without SRQ, an RC, UC or UD Consumer must post the number of receive WRs necessary to handle incoming receives on a given QP. If the Consumer cannot predict the incoming rate on a given QP, because, for example, the connection has a bursty nature, the Consumer must either: post a sufficient number of RQ WRs to handle the highest incoming rate for each connection, or, for RC, let message flow control cause the remote sender to back off until local Consumer posts more WRs.

Either approach is inefficient:

​ • Posting sufficient WRs on each QP to hold the possible incoming rate, wastes WQEs, and the associated Data Segments, when the Receive Queue is inactive. Furthermore, the HCA doesn’t provide a way of reclaiming these WQEs for use on other connections.

​ • Letting the RC message flow control cause the remote sender to back off can add unnecessary latencies, specially if the local Consumer is unaware that the RQ is starving.

A Shared Receive Queue solves this problem by allowing multiple Queue Pairs to share Receive Work Requests and, more importantly, the Data Segments associated with Receive Work Requests. When an incoming Receive Message arrives on any QP that is associated with an SRQ, the HCA uses the next available SRQ WQE to receive the incoming data. The HCA returns Work Completions through the Completion Queue that is associated with the QP that received the incoming Send operation.

简单来说,就是没有SRQ的情况下,因为RC/UC/UD的接收方不知道对端什么时候会发送过来多少数据,所以必须做好最坏的打算,做好突发性收到大量数据的准备,也就是向RQ中下发足量的接收RWQE;另外RC服务类型可以利用流控机制来反压发送方,也就是告诉对端”我这边RQ WQE不够了“,这样发送端就会暂时放缓或停止发送数据。

但是正如前文所说,第一种方法由于是为最坏情况准备的,大部分时候有大量的RQ WQE处于空闲状态未被使用,这对内存是一种极大地浪费;第二种方法虽然不用下发那么多RQ WQE了,但是流控是有代价的,即会增加通信时延。

而SRQ通过允许很多QP共享接收WQE(以及用于存放数据的内存空间)来解决了上面的问题。当任何一个QP收到Send报文后(或带立即数的操作),硬件会从SRQ中取出一个WQE,根据其内容存放接收到的数据,然后硬件通过Completion Queue来返回接收任务的完成信息给对应的上层用户,这样上层用户可以知道哪个QP接收到了数据。

来看一下使用SRQ比使用普通的RQ可以节省多少内存:

假设接受数据的节点上有N对QP,并且每个QP都可能在随机的时间收到连续的M个消息(每个消息都需要消耗一个RQ中的RWQE)。

  • 如果不使用SRQ的话,用户一共需要下发N * M个RQ WQE。
  • 如果使用SRQ的话,用户只需要下发K * M个RQ WQE,而K远小于N。

这个K是可以由用户根据业务来配置的,如果存在大量的并发接收的情况,那么就把K设置大一点,否则K设置成个位数就足够应付一般的情况了。

这样一共节省了(N - K) * M个RQ WQE,RQ WQE本身其实不是很大,大约在几个KB的样子,看起来好像占不了多少内存,但是,真正节省的是用于存放数据的内存空间,用下图来说明:
在这里插入图片描述

上图中的SRQ中有两个RQ WQE,可以看一下RQ WQE的内容,它们是由数个sge(Scatter/Gather Element)组成的,每个sge由一个内存地址,长度和秘钥组成。有了起始地址和长度,sge就可以指向一块连续的内存区域,那么多个sge就可以表示多个彼此离散的连续内存块,我们称多个sge为sgl(Scatter/Gather List)。sge在IB软件协议栈中随处可见(其实在整个Linux都很常见),可以用非常少的空间表示非常大的内存区域,IB的用户都使用sge来指定发送和接收区域的。

可以简单估算下每个sge可以指向多大的内存区域,length是一个32bit的无符号整型,可以表示4GB的空间。假设一个RQ WQE最大可以存放256个sge,那么一个RQ WQE一共就是1TB。当然实际上不可能这么大,这里只是想直观的告诉读者RQ WQE背后可能占用着多大的内存空间。

SRQC

即SRQ Context。同QPC(或RQC)一样,SRQC是用来告知硬件跟SRQ有关的属性的,包括SRQ深度、WQE大小、SRQ buf addr等信息,此外,还必须拥有另外一个字段——limit水线字段。

SRQN

即SRQ Number。同QP一样,每个节点中可能存在多个SRQ,为了标识和区分这些SRQ,每个SRQ都有一个序号,称为SRQN。需要注意,SRQN与QPN是分别管理的,实际使用时,一般通过QPN找到SRQN,再找到SRQC。

SRQ事件相关

以下是与SRQ相关的可能发生的事件的描述。对于这些事件,字段event->element.srq包含收到此异步事件的SRQ的句柄。这些事件仅会在此SRQ所属的代码上下文中生成。

IBV_EVENT_SRQ_LIMIT_REACHED

当一个SRQ被启用并且其中的RWQE数量下降到该SRQ的限制值(limit水线)以下时,将生成此事件。在生成此事件时,硬件会将该SRQ的限制值将被设置为零,以防止重复上报事件。用户收到该事件后,需要向SRQ中下发新的的RWQE,如果需要的话,再通过Modify_srq接口重新设置限制值(limit水线)。
在这里插入图片描述

因为SRQ是多个QP共享的,所以如果深度比较小的情况下,很有可能突然里面的WQE就用完了。所以协议设计了这种机制,来保证用户能够及时干预WQE不够的情况。当然用户可以不使用这个机制,只需要将SRQ Limit的值设为0即可。

IBV_EVENT_SRQ_ERR

当共享接收队列(SRQ)上发生错误时,会生成此事件,该错误会阻止 RDMA 设备从 SRQ 中出列 RWQE 并报告接收完成。 当 SRQ 遇到此错误时,与此 SRQ 关联的所有 QP 都将转换为 IBV_QPS_ERR 状态,并且将为它们生成IBV_EVENT_QP_FATAL 异步事件。任何已转换到错误状态的 QP 必须将其状态修改为 Reset 以进行恢复。

IBV_EVENT_QP_LAST_WQE_REACHED

当与 SRQ 相关联的 QP 由 RDMA 设备自动或由用户明确转换为 IBV_QPS_ERR 状态时,生成该事件。这可能是因为最后一个 WQE 生成了错误的完成,或者 QP 转换为 IBV_QPS_ERR 状态,并且 QP 的接收队列(SRQ)上没有更多的 WQE。 此事件实际上意味着此 QP 将不再从 SRQ 消耗 WQE。 如果 QP 发生错误且未生成此事件,则用户必须销毁与此 SRQ 关联的所有 QP 以及 SRQ 本身,以便回收与违规 QP 关联的所有 WQE。至少,处于错误状态的 QP 必须将其状态更改为 Reset 以进行恢复。

RQ与SRQ差异

PD

RQ是属于QP的,所以RQ的PD就是QP的PD,这就要求:RQ下发RWQE所使用的MR必须与QP同属一个PD,如下图。
在这里插入图片描述

但是SRQ只需要保证其RWQE使用的MR与SRQ同属一个PD即可,也就是说,SRQ与QP可以是不同PD,如下图所示。
在这里插入图片描述

CQ

虽然SRQ关联的很多QP,但每个QP消耗RWQE所产生的CQE,还是放在RQ所关联的CQ中,如下图所示。
在这里插入图片描述

差异汇总

汇总一下差异

RQSRQ
stateRQ state
0x0: Reset
0x1: Initiate
0x2: Ready
0x3: Error
SRQ State
0000: good
0001: Error
RWQE不足无通知SRQ Limit event
通过设定一个水线告诉用户RWQE不足,一旦通知过,则硬件需要将水线设置为0,防止一直上报事件,当下发足够RWQE后需要使用Modify SRQVerb接口重新设置水线,此外,通过Modify SRQVerb接口也可以调整水线,但不能低于当前已下发的RWQE个数

硬件通过async event上报这个事件,软件通过 ibv_get_async_event 接口捕获事件, 事件类型为 IBV_EVENT_SRQ_LIMIT_REACHED

注意,这要求硬件给SRQ CTX中增加一个limit水线字段,用户可以通过接口查询或修改limit水线,此外,应保证修改水线后必须下发足够的RWQE才能使水线生效
CQ每个RQ关联一个CQ,产生CQE有序SRQ不关联CQ(XRC会关联),当QP收到send就从SRQ中取RWQE,并将CQE送到RQ关联的CQ中。不同QP之间无序,同一QP有序
进入错误状态冲刷RWEQ,可通过RESET重置QP,进入错误状态的RQ将无法下发RWQE任何要使用SRQ的QP被强制进入错误状态,只能删除所有关联QP后摧毁SRQ,需要注意,SRQ进入错误状态还可以下发RWQE,但无法使用,此外,任何试图查询或修SRQ的操作都应该失败
QP进入错误状态冲刷RWEQ,可通过RESET重置QP只冲刷已经从SRQ出队的RWQE,也就是QP正在使用的RWEQ,其他还在RWEQ的保持不动
摧毁限制RQ中RWQE冲刷完即可摧毁所有关联的QP必须先进入错误状态,之后等QP排空即可摧毁QP,等所有QP摧毁后,才可以摧毁SRQ
与SRQ关联的QP如果需要通过modify接口重置QP,必须先让QP进入错误状态之后,才可以重置QP摧毁限制
PD校验RQ访问的MR必须与QP处于同一个PDSRQ访问的MR必须与SRQ处于同一PD,而SRQ与QP可以处于不同PD
numberRQ与QP共用一个qpn单独拥有srqn
doorbellUAR中存在和RQ一起使用(通过某个bit区分)
流控有流控(credit)无流控

接口

ibv_create_srq

struct ibv_srq *ibv_create_srq(struct ibv_pd *pd, struct ibv_srq_init_attr *srq_init_attr)

输入参数:
pd 				与共享接收(SRQ)关联的保护域
srq_init_attr 	创建 SRQ 所需的初始属性列表

输出参数:
ibv_srq__attr 	设置结构的实际值

返回值:
指向创建的 SRQ 的指针或失败时的 NULL

ibv_create_srq创建一个共享接收队列(SRQ)。 读取srq_attr-> max_wr和srq_attr-> max_sge以确定所需的SRQ大小,并将其设置为返回时分配的实际值。 如果ibv_create_srq成功,那么max_wr和max_sge将至少与请求的值一样大。

struct ibv_srq定义如下:
struct ibv_srq {
    struct ibv_context      *context;       struct ibv_context from ibv_open_device
    void                    *srq_context;
    struct ibv_pd           *pd;            Protection domain
    uint32_t                handle;
    pthread_mutex_t         mutex;
    pthread_cond_t          cond;
    uint32_t                events_completed;
}

struct ibv_srq_init_attr
{
    void *srq_context;
    struct ibv_srq_attr attr;
};

struct ibv_srq_attr
{
    uint32_t    max_wr;
    uint32_t    max_sge;  //重点!!!!!!!!!sge个数可能大于1,特别是在spdk中
    uint32_t    srq_limit; //常常设为0,由上层软件自己管理,比如spdk
};

ibv_modify_srq

int ibv_modify_srq (struct ibv_srq *srq, struct ibv_srq_attr *srq_attr, int srq_attr_mask)

输入参数:
srq				要修改的 SRQ
srq_attr		指定要修改的 SRQ(输入) /返回所选 SRQ 属性的当前值(输出)
srq_attr_mask 	用于指定要修改哪些 SRQ 属性的位掩码

输出参数:
srq_attr 		返回带有更新值的 struct ibv_srq_attr

返回值:
成功时为 0
错误时为-1,如果调用失败,则将 errno 设置为指示失败的原因。
    
struct ibv_srq_attr {
	uint32_t		max_wr;
	uint32_t		max_sge;
	uint32_t		srq_limit;
};

ibv_modify_srq使用srq_attr中的属性值根据掩码srq_attr_mask修改SRQ srq的属性。 srq_attr是ibv_create_srq下面定义的ibv_srq_attr结构。 参数srq_attr_mask指定要修改的SRQ属性。 它是一个或多个标志的0或按位OR:

IBV_SRQ_MAX_WR //调整 SRQ 的大小
IBV_SRQ_LIMIT //设置 SRQ 限制

如果要修改的任何属性无效,则不会修改任何属性。 此外,并非所有设备都支持调整SRQ的大小。 要检查设备是否支持调整大小,请检查设备能力标志中是否设置了IBV_DEVICE_SRQ_RESIZE位。

一旦SRQ中的WR数降到SRQ限制以下,修改SRQ限制就会使SRQ产生一个 IBV_EVENT_SRQ_LIMIT_REACHED 异步事件。

ibv_destroy_srq

int ibv_destroy_srq(struct ibv_srq * srq)

输入参数:
srq 		要摧毁的SRQ

输出参数:
没有

返回值:
成功时为 0
错误时为 -1,如果调用失败,则将 errno 设置为指示失败的原因。

摧毁SRQ时,必需保证所有关联QP已经解绑。此外,摧毁QP前,需要将QP状态更改的ERROR状态,之后才能摧毁。

ibv_query_srq

int ibv_query_srq(struct ibv_srq * srq, struct ibv_srq_attr *srq_attr)

输入参数:
srq 		指定的 SRQ
srq_attr 	指定 SRQ 的属性

输出参数:
srq_attr 要查询的 SRQ 的属性, 返回 struct ibv_srq_attr

返回值:
成功时为 0
错误时为-1,如果调用失败,则将 errno 设置为指示失败的原因。
    
struct ibv_srq_attr {
	uint32_t		max_wr;
	uint32_t		max_sge;
	uint32_t		srq_limit;
};

ibv_query_srq 返回指定 SRQ 的属性列表和当前值。它通过指针 srq_attr 返回属性,该指针是 ibv_create_srq 中描述的 ibv_srq_attr 结构。如果
srq_attr 中 srq_limit 的值为 0,表示当前无水线,不会生 IBV_EVENT_SRQ_LIMIT_REACHED 事件。

ibv_post_srq_recv

int ibv_post_srq_recv(struct ibv_srq * srq, struct ibv_recv_wr *recv_wr, struct ibv_recv_wr ** bad_recv_wr)

输入参数:
srq 			SRQ的句柄,包含来自 ibv_create_qp 的结构体 ibv_qp
wr 				包含接受缓冲区的第一个工作请求(wr)

输出参数:
bad_recv_wr		执行出错时,指向的错误 wr

返回值:
成功时为 0
错误时为 -1,如果调用失败,则将 errno 设置为指示失败的原因。

ibv_post_srq_recv 将工作请求列表发布到指定的 SRQ。它会在第一次失败时停止处理此列表中的 WR(可以在发布请求时立即检测到),并通过 bad_recv_wr
参数返回此失败的 WR。 只有在 WR 完全执行请求并从相应的完成队列(CQ)检 索到工作完成后,才能安全地重用 WR 使用的缓冲区。 如果将 WR 发布到 UD
QP,则传入消息的全局路由头(GRH)将放置在分散列表中的缓冲区的前 40 个字节中。如果传入消息中不存在 GRH,则前 40 个字节将是未定义的。这意味着
在 UD QP 的所有情况下,传入消息的实际数据将以 40 字节的偏移量开始进入分散列表中的缓冲区。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1048205.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Bytebase x Hacktoberfest 2023 黑客啤酒节开源挑战邀请

🎃十月就要到了,年度开源庆典 Hacktoberfest 即将启动!今年,Bytebase 再次加入 Hacktoberfest,欢迎大家一起参加🍺 Hacktoberfest 是什么 Hacktoberfest Hacker 黑客 Oktoberfest 啤酒节,每…

远程访问:让您随时与电脑保持连接

远程访问可以带来什么? ​如今,我们的大部分工作都是在电脑的帮助下完成的。但是,我们并不总是坐在工作电脑前,随身携带电脑也很不方便,尤其是当工作设备是台式电脑而不是笔记本电脑时。那么,当我们不在…

【EI会议征稿】2023年第二届信号处理、计算机网络与通信国际学术会议(SPCNC2023)

2023年第二届信号处理、计算机网络与通信国际学术会议(SPCNC2023) The 2nd International Conference on Signal Processing, Computer Networks and Communications 2023年第二届信号处理、计算机网络与通信国际学术会议(SPCNC2023&#x…

纷享销客蝉联2023「Cloud100 China 」榜单,综合实力再获认可

近日,2023Cloud 100 China榜单正式发布,榜单由靖亚资本与崔牛会联合推出,纷享销客凭借着过硬的综合实力与卓越的技术创新能力,再次荣登榜单。 【Cloud 100 China】榜单旨在关注中国最具潜力的Cloud公司,上榜的 100 家企…

无需公网IP,实现公网SSH远程登录MacOS【内网穿透】

目录 前言 1. macOS打开远程登录 2. 局域网内测试ssh远程 3. 公网ssh远程连接macOS 3.1 macOS安装配置cpolar 3.2 获取ssh隧道公网地址 3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址 4.1 保留一个固定TCP端口地址 4.2 配置固定TCP端口地址 5. 使用固定TCP端…

AutoDL初体验

AutoDL初体验 真的很给力! 相同的配置,在华为云上价格令人望而却步,AutoDL真的良心价! 搞了个4090体验一下,一小时只要两块五(主要是,之前没有GPU,好多想玩的LLM开源项目都体验不了&…

数字人直播系统开发哪家好?

随着互联网技术的不断发展,直播行业已经成为了一个炙手可热的领域。数字人直播系统作为直播行业的一种新型应用,通过虚拟形象与真人克隆的结合,为用户提供了一种全新的互动体验。那么,在众多开发公司中,哪家公司的数字…

jquery和jquery-ui拖动元素(vue2)

彩色小方块可以任意拖动&#xff0c;红色箭头指向的区域可以拖动 CDN在index.html文件中引入 <link rel"stylesheet" href"//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"><script src"https://code.jquery.com/jquery-3.6.0.min…

水利感知信息系统方案浅析

传统水利感知信息主要包括雨水工情信息&#xff0c;通常是利用信息监测技术、通信技术、网络技术、计算机技术&#xff0c;建立由雨量站、水位站、流量站等组成的雨水工情遥测系统&#xff0c;实现对流域、河流、湖泊、水库、水电站和灌区的固定或移动站点的降水量、水位、流量…

差值结构表达的吸引能

( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有3个节点&#xff0c;AB训练集各由5张二值化的图片组成&#xff0c;让A 中有5个点&#xff0c;B中有1个点&#xff0c;并且重合&#xff0c;统计迭代次数并排序。 其中有6组数据 差值结构 迭代次数 L1 L2 L1 E1 L2…

C函数学习总结

一.内存拷贝函数 void* memcpy(voidr* s1,const void* s2,size_t n); 该函数返回拷贝后的指针。比如说&#xff0c;它可以将一个字符数组缓冲区的内容拷贝到另一个缓冲区中, size_t n可以使用sizeof进行得到。 memmove(void *s1,const void* s2,size_t n); 如果目标区域和源区…

LeetCode 2251. 花期内花的数目:排序 + 二分

【LetMeFly】2251.花期内花的数目&#xff1a;排序 二分 力扣题目链接&#xff1a;https://leetcode.cn/problems/number-of-flowers-in-full-bloom/ 给你一个下标从 0 开始的二维整数数组 flowers &#xff0c;其中 flowers[i] [starti, endi] 表示第 i 朵花的 花期 从 st…

使用docker完成minio服务部署扩容备份迁移生产实践文档

一、minio服务扩容方案 当服务器存储空间不足的时候&#xff0c;需要进行扩容&#xff0c;扩容过程中需要短暂停机时间&#xff0c;预计在一小时内能够完成和恢复 统一注意事项 强烈建议为部署中的所有节点选择基本相似的硬件配置。确保硬件&#xff08;CPU、内存、主板、存…

【Spring Boot】操作Redis数据结构

🌿欢迎来到@衍生星球的CSDN博文🌿 🍁本文主要学习【Spring Boot】操作Redis数据结构 🍁 🌱我是衍生星球,一个从事集成开发的打工人🌱 ⭐️喜欢的朋友可以关注一下🫰🫰🫰,下次更新不迷路⭐️💠作为一名热衷于分享知识的程序员,我乐于在CSDN上与广大开发者…

OOTD耳机 | 国庆出游头戴式耳机推荐|轻装上阵出片神器

国庆假期马上就要来啦&#xff5e; 今天就来分享一款数码神器——头戴式耳机&#xff0c;穿搭拍照必备&#xff0c;特别适合假期出游哦&#xff01;轻装上阵出片神器——轻律Umelody U1头戴式蓝牙耳机&#xff01; 整个设计简约低调&#xff0c;棕色的为主调的包身&#xff0c;…

JMeter 设置请求头信息的详细步骤

在使用 JMeter 的过程中&#xff0c;我们会遇到需要设置请求头信息的场景。比如&#xff1a; POST 传过去的 Body 数据是 json 格式的。需要填添加头信息&#xff1a;Content-Type&#xff1a;application/json。 在 header 中用 token 来传用户的认证信息。 下面&#xff0c;…

服务器vs普通电脑

服务器&#xff0c;是一种高性能计算机&#xff0c;作为网络的节点&#xff0c;存储、处理网络上80&#xff05;的数据、信息&#xff0c;因此也被称为网络的灵魂。那么&#xff0c;服务器与普通电脑有什么不一样呢&#xff1f; 服务器VS普通电脑 普通电脑&#xff0c;通过终…

常用中间件-OAuth2

1. 微服务权限校验Session共享 1.1 微服务权限校验 实现2号方案。使用Redis作为Session统一存储。 首先配置一下Nacos&#xff0c;参考https://blog.csdn.net/weixin_43917045/article/details/132852850 然后为每个服务添加验证机制&#xff0c;先导入依赖 <!-- SpringS…

vs2019配置libcurl环境

一、libcurl下载地址&#xff1a;curl - Download 二、解压下载的压缩包&#xff0c;进入projects\Windows\VC14目录 三、用vs2019打开curl-all.sln工程&#xff0c;选择LIB Debug&#xff0c;x64进行编译 编译后的文件为&#xff1a;curl-8.2.1\build\Win64\VC14\LIB Debug\li…

【c语言中的字符串相关方法介绍】

C语言中有许多字符串相关的函数&#xff0c;用于处理字符串的创建、修改、查找和比较等操作。以下是一些常见的字符串相关函数以及它们的使用方法&#xff1a; strlen&#xff08;字符串长度&#xff09;&#xff1a;用于计算字符串的长度&#xff0c;不包括字符串末尾的空字符…