【vbers】ibv_reg_mr|RDMA

函数说明

原文:ibv_reg_mr() - RDMAmojo RDMAmojo 

struct ibv_mr *ibv_reg_mr(struct ibv_pd *pd, void *addr,
                          size_t length, enum ibv_access_flags access);

描述


ibv_reg_mr() 注册与Protection Domain关联的内存区域 (MR)。通过这样做,允许 RDMA 设备向该内存读取和写入数据。执行此注册需要一些时间,因此当需要快速响应时,不建议在数据路径中执行内存注册。


每次成功注册都会产生一个 MR((在特定 RDMA 设备内)具有唯一lkey 和 rkey 值)。
MR 的起始地址是 addr,它的大小是 length。可以注册的块的最大大小限制为 device_attr.max_mr_size。调用它的进程的虚拟空间中的每个内存地址都可以注册,包括但不限于:

  • 本地内存(变量或数组)
  • 全局内存(变量或数组)
  • 动态分配的内存(使用 malloc() 或 mmap())
  • 共享内存
  • 来自文本段的地址


注册的内存缓冲区不必是页面对齐的。
没有任何方法可以知道能为特定设备注册总大小是多少的内存。


参数 access 描述了 RDMA 设备所需的内存访问属性。它是 0 或以下一个或多个标志的按位或:

IBV_ACCESS_LOCAL_WRITE启用本地写访问:内存区域可用于接收请求或 IBV_WR_ATOMIC_CMP_AND_SWP 或
IBV_WR_ATOMIC_FETCH_AND_ADD 在本地写入远程内容值
IBV_ACCESS_REMOTE_WRITE启用远程写访问。可以使用IBV_WR_RDMA_WRITE或IBV_WR_RDMA_WRITE从远程环境中访问内存区域。
IBV_ACCESS_REMOTE_READ启用远程读取访问:可以使用 IBV_WR_RDMA_READ 从远程环境中访问内存区域
IBV_ACCESS_REMOTE_ATOMIC启用远程原子操作访问(如果支持)。可以使用IBV_WR_ATOMIC_CMP_AND_SWP或IBV_WR_ATOMIC_CMP_AND_SWP从远程环境访问内存区域。
 
IBV_ACCESS_MW_BIND启用内存窗口绑定

 如果设置了 IBV_ACCESS_REMOTE_WRITE 或 IBV_ACCESS_REMOTE_ATOMIC,那么IBV_ACCESS_LOCAL_WRITE也必须被设置,因为只有在允许本地写入的情况下才允许远程写入。

MR 始终enabled 本地读取访问,即可以使用 IBV_WR_SEND、IBV_WR_SEND_WITH_IMM、IBV_WR_RDMA_WRITE、IBV_WR_RDMA_WRITE_WITH_IMM 在本地读取内存区域。

内存注册请求的权限可以是该内存块在操作系统下的权限的全部或子集。例如:操作系统下只读内存不能注册有写权限(本地或远程)。


一个特定的进程可以注册一个或多个内存区域。

参数

NameDirectionDescription
pdin

从 ibv_alloc_pd() 返回的Protection Domain

addrin

虚拟连续内存块的起始地址

lengthin要注册的内存块的大小,以字节为单位。该值必须至少为 1 且小于 dev_cap.max_mr_size
accessin请求的内存区域访问权限

返回值

ValueDescription
MRPointer to the newly allocated Memory Region.
This pointer also contains the following fields:

lkeyThe value that will be used to refer to this MR using a local access
rkeyThe value that will be used to refer to this MR using a remote access

Those values may be equal, but this isn't always guaranteed.

NULLOn failure, errno indicates the failure reason:

EINVALInvalid access value
ENOMEMNot enough resources (either in operating system or in RDMA device) to complete this operation

 例子

注册一个 MR 以只允许本地读写访问并注销它:

struct ibv_pd *pd;
struct ibv_mr *mr;
 
mr = ibv_reg_mr(pd, buf, size, IBV_ACCESS_LOCAL_WRITE);
if (!mr) {
	fprintf(stderr, "Error, ibv_reg_mr() failed\n");
	return -1;
}
 
if (ibv_dereg_mr(mr)) {
	fprintf(stderr, "Error, ibv_dereg_mr() failed\n");
	return -1;

 注册一个 MR 以允许对其进行远程读写:

mr = ibv_reg_mr(pd, buf, size, IBV_ACCESS_LOCAL_WRITE |
		IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_REMOTE_READ);
if (!mr) {
	fprintf(stderr, "Error, ibv_reg_mr() failed\n");
	return -1;
}

 常见问题

为什么 MR 有好处?

MR 注册是一个过程, RDMA 设备获取内存缓冲区并准备将其用于本地和/或远程访问。

我可以多次注册同一个内存块吗?

是的。可以多次注册同一个内存块或其中的一部分。甚至可以使用不同的访问标志来执行这些内存注册。

可以注册的总内存大小是多少?

没有任何方法可以知道可以注册的内存总大小是多少。理论上,这个值没有任何限制。但是,如果您希望注册大量内存(数百 GB),那么low-level drivers的默认值可能还不够;查看"Device Specific"部分以了解如何更改默认参数值以解决此问题。

我是否可以用比操作系统允许的更多的权限访问使用RDMA设备的内存?

否。在内存注册期间,驱动程序会检查内存块的权限,并检查请求的权限超出系统分配给该内存块的权限。

我可以在没有此注册的情况下在 RDMA 中使用内存块吗?

基本上不行。但是,有些 RDMA 设备可以在不需要内存注册(内联数据发送)的情况下读取内存。

ibv_reg_mr() 失败,这是什么原因?

由于以下原因,ibv_reg_mr() 可能会失败:

  • 错误的属性:错误的权限或错误的内存缓冲区
  • 没有足够的资源来注册此内存缓冲区

如果这是您注册的第一个缓冲区,则可能是第一个原因。如果已经注册了很多缓冲区后内存注册失败,可能是因为没有足够的资源来注册这个内存缓冲区:大多数时候,RDMA设备中用于虚拟地址转换的资源=>实际地址。在这种情况下,您可能需要检查如何增加此 RDMA 设备可以注册的内存量。

我可以在我的进程中注册多个 MR 吗?

是的你可以。

Device Specific

Mellanox Technologies

ibv_reg_mr() failed, what is the reason for this?

If you are using one of the ConnectX HCAs family, it is a matter of configuration; you should increase the total size of memory that can be registered. This can be accomplished by setting the value of the parameter log_num_mtt of the module mlx4_core.

Adding the following line to the file /etc/modprobe.conf or to /etc/modprobe.d/mlx4_core.conf (depends on the Linux distribution that you are using) should solve this problem:
options mlx4_core log_num_mtt=24

理解内存注册(Memory Registration)

摘自:[SPDK/NVMe存储技术分析]015 - 理解内存注册(Memory Registration) - vlhn - 博客园

使用RDMA, 必然关系到内存区域(Memory Region)的注册问题。在本文中,我们将以mlx5 HCA(HCA:在Infiniband/RoCE规范中,将RDMA网卡称为HCA,全称为Host Channel Adapter)卡为例回答如下几个问题:

  1. 为什么需要注册内存区域?
  2. 注册内存区域有嘛好处?
  3. 注册内存区域的实现过程

1. 为什么需要注册内存区域?

      RDMA引擎也是一种DMA引擎,由于DMA设备只访问物理内存地址,因此,DMA引擎需要主机系统内存的物理地址连续,这一点无可非议,因为如果物理地址不连续,即便DMA引擎知道buffer开始的地址(虚拟地址)和buffer长度,也不知道怎么搬数据。

试想一下,如果让DMA引擎知道如何将主机系统内存的虚拟地址(VA)如何翻译成对应的物理地址(PA),先姑且不论设计和实现DMA引擎的固件(firemware)有多么复杂,从常理上讲也说不通,本来是应该由操作系统的驱动干的事情,为啥让固件去干?设计网卡及I/O卡固件的人哪管你操作系统是Linux还是Windows?! 而且,各种I/O卡的DMA引擎相对于主机(Host)的CPU和系统内存(System Memory)来说,不过就是一帮打杂的伙计而已,让伙计们知道主人怎么管理系统内存虚拟地址与物理地址的映射关系,从宏观设计的角度讲,完全没有那个必要。

        当然,RDMA对内存区域的使用还有特殊要求。

  • 01 - 在数据传输过程中,应用程序不得修改相应的内存buffer里的内容,因为工作请求(WR)放知道工作队列上,其完成状态就完全受控于RDMA网卡了;
  • 02 - 内存buffer的物理地址与虚拟地址映射关系必须是固定的,在数据传输过程中,对应的内存页不得被操作系统交换出去。

换句话说,一旦注册了某个内存区域,该区域就将被RDMA硬件所访问。那么,内存注册意味着发生了如下两件事情:

  • 01 - 内存区域被操作系统内核锁定,防止物理地址(内存里存放的数据)被交换到硬盘上。(在Linux操作系统中,使用mlock调用来执行这一操作)
  • 02 - (系统执行)RDMA硬件的驱动(的程序)将虚拟内存地址转换为物理内存地址,然后将这一对应关系交给RDMA硬件去使用。

特别说明: 虚拟地址连续 != 物理地址连续,下面引用IBTA技术规范中给出的一张图(注册之后的虚拟内存缓冲区与物理内存页的映射关系),一目了然!

2. 注册内存区域有嘛好处?

注册内存区域本质上就是Memory Pinning(内存固定),因为典型的DMA操作通常就需要Memory Pinning。

被注册的内存区域在数据传输完成之前不被打扰,最大的好处就是保证了RDMA数据传输的高吞吐量。

注: 关于Pinned and Non-Pinned Memory的论述, 请参考这里

... pinned memory is much more expensive to allocate and deallocate but 
provides higher transfer throughput for large memory transfers.

3. 注册内存区域的实现过程 

对于应用来说,注册一段内存区域的函数是ibv_reg_mr()。让我们从这个函数开始。

[SPDK/NVMe存储技术分析]015 - 理解内存注册(Memory Registration) - vlhn - 博客园

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

导航