RDMA Send Receive操作

news2025/1/18 18:49:43

1. 前言

RDMA指的是远程直接内存访问,这是一种通过网络在两个应用程序之间搬运缓冲区里的数据的方法。RDMA与传统的网络接口不同,因为它绕过了操作系统。这允许实现了RDMA的程序具有如下特点:

  • 绝对的最低时延
  • 最高的吞吐量
  • 最小的CPU足迹 (也就是说,需要CPU参与的地方被最小化)

2. RDMA Verbs操作

使用RDMA, 我们需要有一张实现了RDMA引擎的网卡。我们把这种卡称之为HCA(主机通道适配器)。 适配器创建一个贯穿PCIe总线的从RDMA引擎到应用程序内存的通道。一个好的HCA将在导线上执行的RDMA协议所需要的全部逻辑都在硬件上予以实现。这包括分组,重组以及流量控制和可靠性保证。因此,从应用程序的角度看,只负责处理所有缓冲区即可。

在RDMA中我们使用内核态驱动建立一个数据通道。我们称之为命令通道(Command Channel)。使用命令通道,我们能够建立一个数据通道(Data Channel),该通道允许我们在搬运数据的时候完全绕过内核。一旦建立了这种数据通道,我们就能直接读写数据缓冲区。

建立数据通道的API是一种称之为"verbs"的API。"verbs" API是由一个叫做OFED的Linux开源项目维护的。在站点http://www.openfabrics.org上,为Windows WinOF提供了一个等价的项目。"verbs" API跟你用过的socket编程API是不一样的。但是,一旦你掌握了一些概念后,就会变得非常容易,而且在设计你的程序的时候更简单。

2. Queue Pairs

RDMA操作开始于“搞”内存。当你在对内存进行操作的时候,就是告诉内核这段内存名花有主了,主人就是你的应用程序。于是,你告诉HCA,就在这段内存上寻址,赶紧准备开辟一条从HCA卡到这段内存的通道。我们将这一动作称之为注册一个内存区域(MR)。一旦MR注册完毕,我们就可以使用这段内存来做任何RDMA操作。在下面的图中,我们可以看到注册的内存区域(MR)和被通信队列所使用的位于内存区域之内的缓冲区(buffer)。

RDMA Memory Registration

struct ibv_mr {
    struct ibv_context     *context;
    struct ibv_pd          *pd;
    void                   *addr;
    size_t                  length;
    uint32_t                handle;
    uint32_t                lkey;
    uint32_t                rkey;
};

RDMA硬件不断地从工作队列(WQ)中去取工作请求(WR)来执行,执行完了就给完成队列(CQ)中放置工作完成通知(WC)。这个WC意思就是Work Completion。表示这个WR RDMA请求已经被处理完成,可以从这个Completion Queue从取出来,表示这个RDMA请求已经被处理完毕。

RDMA通信基于三条队列(SQ, RQ和CQ)组成的集合。 其中, 发送队列(SQ)和接收队列(RQ)负责调度工作,他们总是成对被创建,称之为队列对(QP)。当放置在工作队列上的指令被完成的时候,完成队列(CQ)用来发送通知。

当用户把指令放置到工作队列的时候,就意味着告诉HCA那些缓冲区需要被发送或者用来接受数据。这些指令是一些小的结构体,称之为工作请求(WR)或者工作队列元素(WQE)。 WQE的发音为"WOOKIE",就像星球大战里的猛兽。一个WQE主要包含一个指向某个缓冲区的指针。一个放置在发送队列(SQ)里的WQE中包含一个指向待发送的消息的指针。一个放置在接受队列里的WQE里的指针指向一段缓冲区,该缓冲区用来存放待接受的消息。

下面我们来看一下RDMA中的Work Request(SendWR和ReceWR)

RDMA Send Work Request请求

struct ibv_send_wr {
    uint64_t                wr_id;
    struct ibv_send_wr     *next;
    struct ibv_sge         *sg_list;
    int                     num_sge;
    enum ibv_wr_opcode      opcode;
    int                     send_flags;
    uint32_t                imm_data;       /* in network byte order */
    union {
            struct {
                    uint64_t        remote_addr;
                    uint32_t        rkey;
            } rdma;
            struct {
                    uint64_t        remote_addr;
                    uint64_t        compare_add;
                    uint64_t        swap;
                    uint32_t        rkey;
            } atomic;
            struct {
                    struct ibv_ah  *ah;
                    uint32_t        remote_qpn;
                    uint32_t        remote_qkey;
            } ud;
    } wr;
};

RDMA Receive Work Request请求

struct ibv_recv_wr {
    uint64_t                wr_id;
    struct ibv_recv_wr     *next;
    struct ibv_sge         *sg_list;
    int                     num_sge;
};

RDMA是一种异步传输机制。因此我们可以一次性在工作队列里放置好多个发送或接收WQE。HCA将尽可能快地按顺序处理这些WQE。当一个WQE被处理了,那么数据就被搬运了。 一旦传输完成,HCA就创建一个完成队列元素(CQE)并放置到完成队列(CQ)中去。 相应地,CQE的发音为"COOKIE"。

RDMA Complete Queue Element

c++ struct ibv_wc { uint64_t wr_id; enum ibv_wc_status status; enum ibv_wc_opcode opcode; uint32_t vendor_err; uint32_t byte_len; uint32_t imm_data; /* in network byte order */ uint32_t qp_num; uint32_t src_qp; int wc_flags; uint16_t pkey_index; uint16_t slid; uint8_t sl; uint8_t dlid_path_bits; };

3. RDMA Send/Receive

让我们看个简单的例子。在这个例子中,我们将把一个缓冲区里的数据从系统A的内存中搬到系统B的内存中去。这就是我们所说的消息传递语义学。接下来我们要讲的一种操作为SEND,是RDMA中最基础的操作类型。

3.1 第一步

第1步:系统A和B都创建了他们各自的QP的完成队列(CQ), 并为即将进行的RDMA传输注册了相应的内存区域(MR)。 系统A识别了一段缓冲区,该缓冲区的数据将被搬运到系统B上。系统B分配了一段空的缓冲区,用来存放来自系统A发送的数据。

3.2 第二步

第二步:系统B创建一个WQE并放置到它的接收队列(RQ)中。这个WQE包含了一个指针,该指针指向的内存缓冲区用来存放接收到的数据。系统A也创建一个WQE并放置到它的发送队列(SQ)中去,该WQE中的指针执行一段内存缓冲区,该缓冲区的数据将要被传送。

3.3 第三步

第三步:系统A上的HCA总是在硬件上干活,看看发送队列里有没有WQE。HCA将消费掉来自系统A的WQE, 然后将内存区域里的数据变成数据流发送给系统B。当数据流开始到达系统B的时候,系统B上的HCA就消费来自系统B的WQE,然后将数据放到该放的缓冲区上去。在高速通道上传输的数据流完全绕过了操作系统内核。

3.4 第四步

第四步:当数据搬运完成的时候,HCA会创建一个CQE。 这个CQE被放置到完成队列(CQ)中,表明数据传输已经完成。HCA每消费掉一个WQE, 都会生成一个CQE。因此,在系统A的完成队列中放置一个CQE,意味着对应的WQE的发送操作已经完成。同理,在系统B的完成队列中也会放置一个CQE,表明对应的WQE的接收操作已经完成。如果发生错误,HCA依然会创建一个CQE。在CQE中,包含了一个用来记录传输状态的字段。

我们刚刚举例说明的是一个RDMA Send操作。在IB或RoCE中,传送一个小缓冲区里的数据耗费的总时间大约在1.3µs。通过同时创建很多WQE, 就能在1秒内传输存放在数百万个缓冲区里的数据。

4. 总结

在这博客中,我们学习了如何使用RDMA verbs API。同时也介绍了队列的概念,而队列概念是RDMA编程的基础。最后,我们演示了RDMA send操作,展现了缓冲区的数据是如何在从一个系统搬运到另一个系统上去的。

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

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

相关文章

《游戏编程模式》学习笔记(四) 观察者模式 Observer Pattern

定义 观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。 这是定义,看不懂就看不懂吧,我接下来举个例子慢慢说 为什么我们需要观察者模式 我们看一个很简…

二叉树的构建及遍历

题目链接:https://www.nowcoder.com/practice/4b91205483694f449f94c179883c1fef?tpId60&&tqId29483&rp1&ru/activity/oj&qru/ta/tsing-kaoyan/question-ranking 题目 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建…

视频播放相关记录

一、场景 App应用测试在二次回归时,提出了安卓端视频定位不准的问题。 二、分析 代码层面使用了安卓原始的MediaPlayer中的seekTo接口来定位: mp.setOnInfoListener(new MediaPlayer.OnInfoListener() {Overridepublic boolean onInfo(MediaPlayer mp, i…

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验1

多旋翼飞控底层算法开发系列实验 | 多旋翼动力系统设计实验1 01 多旋翼动力系统简介 多旋翼无人机的动力系统通常包括螺旋桨、电机、电调以及电池。动力系统是多旋翼最重要的组成部分,它决定了多旋翼的主要性能,如悬停时间、载重能力、飞行速度和飞行距…

The kernel appears to have died. It will restart automatically.

在使用pytorch运行一个小案例时,绘制图像时出现了 The kernel appears to have died. It will restart automatically. 查看 anaconda prompt OMP: Error #15: Initializing libiomp5md.dll, but found libiomp5md.dll already initialized. OMP: Hint This means…

NestJs 中使用 mongoose

在 NestJS 中链接 MongoDB 有两种方法。一种方法就是使用TypeORM来进行连接,另外一种方法就是使用Mongoose。 此笔记主要是记录使用Mongoose的。所以我们先安装所需的依赖: npm i nestjs/mongoose mongoose安装完成后,需要在AppModule中引入…

前端基础学习笔记

目录 1.HTML部分1.HTML简介2.实例介绍3.标题4.段落5.链接6.图像7.表格8.速查列表1.基本文档2.基本标签3.文本格式化4.链接5.图片6.无序列表7.有序列表8.定义列表9.表格10.框架11.表单 2.CSS部分1.CSS简介1.什么是CSS2.为什么使用CSS3.CSS作用 2.基本用法1.CSS语法2.CSS应用方式…

Failed to resolve component: v-data-table“. vue3 + vuefity 使用 v-data-table 报错解决

在使用 vue3 vuetify 开发项目的过程中用到了 v-data-table 组件,结果在使用的过程中发现加载失败控制台报错。 [Vue warn]: Failed to resolve component: VDataTable解决方案: import { VDataTable } from vuetify/labs/VDataTable参考文档: https:…

双碳目标下基于“遥感+”多技术融合在碳储量、碳排放、碳循环、温室气体教程

详情点击链接:双碳目标下基于“遥感”多技术融合在碳储量、碳排放、碳循环、温室气体教程 一:双碳视角下遥感技术的研究方向 1.双碳背景及遥感的现实需求 2.全球碳库、碳收支及碳循环现状 3.碳储量、碳收支与碳循环中的遥感技术 4.ENVI及ArcGIS软件一体…

(三) CUDA 硬件实现

一组带有on-chip 共享内存的SIMD多处理器 GPU可以被看作一组多处理器, 每个多处理器使用单一指令,多数据架构(SIMD)【单指令流多数据流】 在任何给定的时钟周期内,多处理器的每个处理器执行同一指令,但操作不同的数据 每个多处理器使用以下…

广告ROI可洞察到订单转化率啦

toB广告营销人的一日三问&#xff1a; 如何实现线索增长&#xff1f;如何获取更多高质量线索&#xff1f;如何能用更少的钱拿到更多高质量的线索&#xff1f; < 广告营销的终极目标&#xff0c;就是提升ROI > 从ROI公式中&#xff0c;可以找到提升广告营销ROI的路径&…

Linux:shell脚本循环语句

目录 一、循环含义 二、echo命令 三、for 3.1.将1到100累加求和 3.2批量添加用户 3.3 根据IP地址检查主机状态 四、 while 和 until 4.1 猜价格 4.2 1-100求和 一、循环含义 循环含义 将某代码段重复运行多次&#xff0c;通常有进入循环的条件和退出循环的条件 重复…

kali搭建vulhub漏洞靶场

安装kali 下载kali作为虚拟环境&#xff0c; Get Kali | Kali Linux 通过vmvare打开&#xff0c;默认账号密码kali/kali 修改root密码 su passwd root 如果一些配置普通用户做不了就切换kali&#xff0c;或sudo 命令 kali配置 apt换源 echo > /etc/apt/sources.list v…

java对大文件分片上传

这里记录一下&#xff0c;Java对大文件的切分&#xff0c;和后端接口分片上传的实现逻辑 正常&#xff0c;前后端分离的项目其实是前端去切分文件&#xff0c;后端接口接收到切分后的分片文件去合并&#xff0c;这里都用java来记录一下。特别说明&#xff1a;我这里用的是zip包…

Codeforces Round 888 (Div. 3)ABC

Codeforces Round 888 (Div. 3) 目录 A. Escalator Conversations题目大意思路代码 B. Parity Sort题目大意思路代码 C. Tiles Comeback题目大意思路代码 A. Escalator Conversations 题目大意 判断有多少个人能够通过站在楼梯上的操作和VLAD一样高或者是VLAD通过站在楼梯上的…

6.1 MyBatis基础

1.MyBatis概述 MyBatis本是apache的一个开源项目iBatis&#xff0c;2010年这个项目由apache software foundation迁移到了google code&#xff0c;并且改名为MyBatis&#xff0c;2013年11月MyBatis又被迁移到Github。 MyBatis是一个支持普通SQL查询、存储过程以及高级映射的持…

欧拉算法与埃氏筛法比较

#include<iostream> using namespace std; bool data[100000005]; // zhishu用于存储质数的数组 &#xff0c;cnt下标 int zhishu[100000000],cnt0;int main() {data[1] 1;// 1表示素数 int n;cin >> n;// 循环遍历for(int i2;i<n;i){if(data[i] 0){// 表明是…

嵌入式学习之C语言指针部分复习

今天主要把C语言的指针部分再次认真的复习了一下&#xff0c;对于指针的整体框架有了更加深刻的理解&#xff0c;特别要重点区分函数指针&#xff0c;指针函数&#xff0c;数组指针&#xff0c;指针数组部分&#xff0c;对于这部分的应用回非常的重要&#xff0c;而且C语言指针…

海龟绘图——长方体(包含建立和销毁的过程)

运行结果&#xff1a; 代码&#xff1a; import turtle turtle.setup(1024,1024,200,200)# 移动画笔 turtle.penup() turtle.goto(-200,200) turtle.pendown() # 绘制第一条实线 turtle.setheading(0) turtle.forward(300) # 绘制第二条实线 turtle.setheading(18045) turtle.…