Skip to content

Latest commit

 

History

History
201 lines (165 loc) · 8.1 KB

AI 查询的 RDMA.md

File metadata and controls

201 lines (165 loc) · 8.1 KB

ibv_dm

struct ibv_dm 是 RDMA (远程直接内存访问) 接口中的一个数据结构,用于表示 设备内存(Device Memory, DM)。设备内存是 RDMA 硬件设备的一部分,它允许用户将数据直接存储在 RDMA 设备中,而不是通过主机内存。这种机制可以降低数据传输的延迟并提高性能,尤其是在某些性能敏感的应用场景中。

以下是结构体成员的详细介绍:


结构体定义

struct ibv_dm {
    struct ibv_context *context;
    int (*memcpy_to_dm)(struct ibv_dm *dm, uint64_t dm_offset,
                        const void *host_addr, size_t length);
    int (*memcpy_from_dm)(void *host_addr, struct ibv_dm *dm,
                          uint64_t dm_offset, size_t length);
    uint32_t comp_mask;
    uint32_t handle;
};

字段解释

1. struct ibv_context *context

  • 类型: 指针,指向 struct ibv_context
  • 作用:
    • 表示与 RDMA 设备相关的上下文环境。
    • 这是 RDMA 核心数据结构,用于表示与设备的通信接口。
    • context 中包含了设备的基本信息,以及进行 RDMA 操作时需要用到的资源。

2. int (*memcpy_to_dm)(struct ibv_dm *dm, uint64_t dm_offset, const void *host_addr, size_t length)

  • 类型: 函数指针。
  • 作用:
    • 将数据从主机内存(host_addr)复制到设备内存(dm)的指定偏移位置(dm_offset)。
    • 参数说明:
      • struct ibv_dm *dm:目标设备内存。
      • uint64_t dm_offset:设备内存中的偏移地址。
      • const void *host_addr:主机内存的起始地址。
      • size_t length:要复制的数据长度。
    • 返回值:
      • 成功返回 0,失败返回非 0 错误码。

3. int (*memcpy_from_dm)(void *host_addr, struct ibv_dm *dm, uint64_t dm_offset, size_t length)

  • 类型: 函数指针。
  • 作用:
    • 将数据从设备内存(dm)的指定偏移位置(dm_offset)复制到主机内存(host_addr)。
    • 参数说明:
      • void *host_addr:主机内存的目标地址。
      • struct ibv_dm *dm:源设备内存。
      • uint64_t dm_offset:设备内存中的偏移地址。
      • size_t length:要复制的数据长度。
    • 返回值:
      • 成功返回 0,失败返回非 0 错误码。

4. uint32_t comp_mask

  • 类型: 无符号 32 位整数。
  • 作用:
    • 用于扩展设备内存结构的兼容性掩码(Compatibility Mask)。
    • 在 RDMA 核心库中,comp_mask 通常用于指示哪些字段是有效的。
    • 通过该掩码可以在向后兼容的情况下扩展数据结构,而不会破坏现有代码的功能。

5. uint32_t handle

  • 类型: 无符号 32 位整数。
  • 作用:
    • 表示设备内存的标识符(Handle)。
    • 这是 RDMA 核心库使用的内部引用,用于标识特定的设备内存。
    • RDMA 操作会通过该句柄与设备内存进行交互。

用途

struct ibv_dm 的主要作用是抽象 RDMA 设备内存的管理功能。它允许用户直接管理设备内存,并提供高效的数据传输机制。

  • 设备内存的优势:

    1. 低延迟: 数据可以直接存储在 RDMA 设备中,避免通过主机内存进行多余的传输。
    2. 高吞吐: 在某些场景下,直接使用设备内存可以提高数据传输的吞吐量。
    3. 更高效的 CPU 使用: 避免 CPU 多次拷贝内存。
  • 常见场景:

    • 传输固定格式的小型控制消息。
    • 存储用于数据直接访问的临时数据。
    • 优化 GPU-RDMA 的数据路径(如 GPU 内存与设备内存之间的直接通信)。

示例代码

以下是一个使用 ibv_dm 的简单示例,展示如何将数据从主机复制到设备内存并再复制回来:

#include <infiniband/verbs.h>
#include <stdio.h>
#include <string.h>

int main() {
    struct ibv_context *ctx;      // RDMA 设备上下文
    struct ibv_dm *dm;            // 设备内存
    const char *data = "Hello RDMA!";
    char buffer[128] = {0};
    size_t length = strlen(data) + 1;

    // 假设已经初始化 RDMA 设备上下文 ctx...

    // 分配设备内存
    struct ibv_alloc_dm_attr dm_attr = {
        .length = 128,  // 分配 128 字节的设备内存
    };
    dm = ibv_alloc_dm(ctx, &dm_attr);
    if (!dm) {
        perror("Failed to allocate device memory");
        return -1;
    }

    // 将数据从主机内存复制到设备内存
    if (dm->memcpy_to_dm(dm, 0, data, length)) {
        perror("Failed to copy to device memory");
        return -1;
    }

    // 将数据从设备内存复制回主机内存
    if (dm->memcpy_from_dm(buffer, dm, 0, length)) {
        perror("Failed to copy from device memory");
        return -1;
    }

    printf("Data from device memory: %s\n", buffer);

    // 释放设备内存
    ibv_free_dm(dm);
    return 0;
}

总结

struct ibv_dm 是 RDMA 编程中管理设备内存的重要工具,其核心功能包括:

  1. 提供主机和设备内存之间的数据拷贝接口。
  2. 允许用户将性能敏感的数据存储在设备内存中,减少内存拷贝和传输延迟。
  3. 提供一个抽象层,使得设备内存的使用更加灵活和高效。

ibv_cq vs ibv_cq_ex

union {
    struct ibv_cq *cq;          // 普通 Completion Queue (CQ)
    struct ibv_cq_ex *cq_ex;    // 扩展 Completion Queue (CQ)
} cq_s;
  • struct ibv_cq *cq
    • 作用: 指向一个普通的 完成队列(Completion Queue, CQ)
    • 用途: 用于普通 RDMA 操作时的工作请求(Work Request, WR)的完成通知。
    • 普通 CQ 的功能: 提供基本的完成事件处理,适合较简单的 RDMA 应用场景。
  • struct ibv_cq_ex *cq_ex
    • 作用: 指向一个 扩展完成队列(Extended Completion Queue, CQ)
    • 用途: 用于扩展的 RDMA 操作(更高级功能),例如具有更多元数据的完成通知。
    • 扩展 CQ 的功能:
      • 提供比普通 CQ 更详细的操作结果信息(例如时间戳等)。
      • 支持更复杂的 RDMA 操作场景。

.为什么使用联合体?

  • RDMA 编程中,ibv_cqibv_cq_ex 分别用于不同的场景:
    • 如果程序只需要普通 CQ 的功能,使用 ibv_cq 即可。
    • 如果程序需要扩展 CQ 的功能,则使用 ibv_cq_ex
  • 由于普通 CQ 和扩展 CQ 是互斥的,一个 RDMA 操作不会同时使用这两种 CQ 类型,所以将它们放在联合体中以节省内存。
  • cq_s 可以通过访问 cqcq_ex 来灵活处理两种 CQ 类型,而不需要为每种类型分配独立的空间。

普通 CQ 和扩展 CQ 的区别:

  • 普通 CQ(ibv_cq): 提供基本的完成事件处理,适合简单的 RDMA 应用。
  • 扩展 CQ(ibv_cq_ex): 提供更详细的操作结果信息,适合复杂的 RDMA 应用。

应用层 - UDP 应用程序
传输层 - UDP
网络层 - IP/RoCE v2
数据链路层 - 以太网/RoCE v2
物理层 - 物理网络

限制 1:TCP/IP 堆栈处理引入了数十微秒的延迟。当TCP协议栈接收和发送消息时,内核需要进行多次上下文切换,每次消耗5-10微秒。另外,至少三个数据副本和协议工作依赖于 CPU。这意味着仅仅协议处理就会带来几十微秒的固定延迟。协议栈的延迟成为最明显的瓶颈。


(0 -- 1 -- 2 -- 3 -- 4 -- 0)降低 QP 队列对的使用

全连接拓扑:每台机器创建 n-1 个 QP,分别与其余 n-1台机器建立连接。每对机器之间都有直接的 QP ,用于通信。 优点:

  • 每台机器可以直接与任意其他机器通信,延迟最低。
  • 不依赖中间节点,无需数据转发。 缺点:
  • 随着机器数量 nnn 增加,QP 数量呈 O(n2)O(n^2)O(n2) 增长,资源消耗巨大。
  • 对于大规模集群,无法扩展。 适用场景 小规模集群(如 n≤16n \leq 16n≤16),对延迟要求极高的场景。