DOCA 文档 v2.10.0

DOCA 存储零拷贝 Comch 到 RDMA 应用程序指南

DOCA 存储零拷贝 Comch 到 RDMA (comch_to_rdma) 是 doca_storage_zero_copy_initiator_comch (initiator_comch) 和 doca_storage_zero_copy_target_rdma (target_rdma) 之间的通信桥梁。这使 initiator_comch 免受 target_rdma 细节的影响。

  1. Comch_to_rdma 通过 TCP 连接到 target_rdma。

  2. Comch_to_rdma 创建一个 comch 服务器并等待 initiator_comch 连接。

  3. Comch_to_rdma 等待来自 initiator_comch 的控制消息并对其做出适当的反应。

    信息

    每个线程建立两个 RDMA 连接,以避免大型 RDMA 数据传输干扰或延迟较小的 IO 消息。

comch_to_rdma_system_design-version-1-modificationdate-1734469970640-api-v2.png

DOCA 存储零拷贝 Comch 到 RDMA 分三个阶段执行

  1. 准备.

  2. 数据路径.

  3. 拆卸.

准备阶段

在此阶段,应用程序执行以下操作

  1. 通过 TCP 连接到 target_rdma。

  2. 创建一个 DOCA Comch 服务器并等待客户端连接。

  3. 等待来自 initiator_comch 的“配置数据路径”控制消息(包括缓冲区计数、缓冲区大小、doca_mmap 导出详细信息)。

    1. 使用来自 initiator_comch 的导出详细信息创建 doca_mmap,然后重新导出它以提供对 target_rdma 的访问。

    2. 向 target_rdma 发送配置数据路径控制消息。

    3. 等待来自 target_rdma 的配置数据路径控制消息响应,状态为成功。

    4. 向 initiator_comch 发送配置数据路径控制消息响应。

  4. 等待来自 initiator_comch 的“启动数据路径连接”控制消息。

    1. 创建 comch 数据路径对象。

    2. 创建 N 个 RDMA 连接,与 target_rdma 交换连接详细信息。

    3. 将启动数据路径连接控制消息中继到 target_rdma。

    4. 等待来自 target_rdma 的启动数据路径连接控制消息响应,状态为成功。

    5. 向 initiator_comch 发送启动数据路径连接控制消息响应。

  5. 等待来自 initiator_comch 的“启动存储”控制消息。

    1. 验证所有 RDMA 和 Comch 连接是否准备就绪可以使用。

    2. 向 target_rdma 发送启动存储控制消息。

    3. 等待来自 target_rdma 的启动存储控制消息响应,状态为成功。

    4. 启动数据路径线程。

    5. 向 initiator_comch 发送启动存储控制消息响应。

comch_to_rdma_preparation_stage-version-1-modificationdate-1734469970347-api-v2.png

数据路径阶段

此阶段启动数据路径线程。每个线程首先提交接收 comch 和 RDMA 任务,然后执行一个紧密循环,尽可能快地轮询进度引擎 (PE),直到收到“数据路径停止”IO 消息。数据路径线程的工作是被动的,因此在任务完成回调中执行。当从 initiator_comch 接收到每个 IO 消息时,它将被转发到存储应用程序。同样,当从 target_rdma 接收到每个 IO 消息响应时,它将被中继回 initiator_comch。

拆卸阶段

在此阶段,应用程序执行以下操作

  1. 等待来自 initiator_comch 的销毁对象控制消息。

  2. 向 target_rdma 发送销毁对象控制消息。

  3. 等待来自 target_rdma 的销毁对象控制消息响应。

  4. 销毁数据路径对象。

  5. 向 initiator_comch 发送销毁对象控制消息响应。

  6. 销毁控制路径对象。

此应用程序利用以下 DOCA 库

此应用程序作为存储零拷贝应用程序集的一部分进行编译。有关编译说明,请参阅 NVIDIA DOCA 存储零拷贝

应用程序执行

注意

此应用程序只能在主机上运行。

DOCA 存储零拷贝 Comch 到 RDMA 以源代码形式提供。因此,在执行应用程序之前需要进行编译。

  • 应用程序使用说明

    复制
    已复制!
                

    Usage: doca_storage_zero_copy_comch_to_rdma [DOCA Flags] [Program Flags]   DOCA Flags:   -h, --help                        Print a help synopsis   -v, --version                     Print program version information   -l, --log-level                   Set the (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>   --sdk-log-level                   Set the SDK (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>   -j, --json <path>                 Parse all command flags from an input json file   Program Flags:   -d, --device                      Device identifier   -r, --representor                 Device host side representor identifier   --cpu                             CPU core to which the process affinity can be set   --storage-server                  One or more storage server addresses in <ip_addr>:<port> format   --command-channel-name            Name of the channel used by the doca_comch_server. Default: storage_zero_copy_comch

    信息

    此用法打印输出可以使用 -h (或 --help)选项打印到命令行

    复制
    已复制!
                

    ./doca_storage_zero_copy_comch_to_rdma -h

    有关更多信息,请参阅“命令行标志”部分。

  • 在 BlueField 上运行应用程序的 CLI 示例

    复制
    已复制!
                

    ./doca_storage_zero_copy_comch_to_rdma -d 03:00.0 -r 3b:00.0 --storage-server 172.17.0.1:12345 --cpu 12

    注意

    DOCA Comch 设备 PCIe 地址 (03:00.0) 和 DOCA Comch 设备表示器 PCIe 地址 (3b:00.0) 都应与所需 PCIe 设备的地址匹配。

  • 该应用程序还支持基于 JSON 的部署模式,其中所有命令行参数都通过 JSON 文件提供

    复制
    已复制!
                

    ./doca_storage_zero_copy_comch_to_rdma --json [json_file]

    例如

    复制
    已复制!
                

    ./doca_storage_zero_copy_comch_to_rdma --json doca_storage_zero_copy_comch_to_rdma_params.json

    注意

    在执行之前,请确保使用的 JSON 文件包含正确的配置参数,尤其是部署所需的 PCIe 地址。

命令行标志

标志类型

短标志

长标志/JSON 键

描述

JSON 内容

通用标志

h

help

打印帮助概要

N/A

v

version

打印程序版本信息

N/A

l

log-level

设置应用程序的日志级别

  • DISABLE=10

  • CRITICAL=20

  • ERROR=30

  • WARNING=40

  • INFO=50

  • DEBUG=60

  • TRACE=70(需要使用 TRACE 日志级别支持进行编译)

复制
已复制!
            

"log-level": 60

N/A

sdk-log-level

设置程序的日志级别

  • DISABLE=10

  • CRITICAL=20

  • ERROR=30

  • WARNING=40

  • INFO=50

  • DEBUG=60

  • TRACE=70

复制
已复制!
            

"sdk-log-level": 40

j

json

从输入 JSON 文件解析所有命令标志

N/A

程序标志

d

device

DOCA 设备标识符。以下之一

  • PCIe 地址:3b:00.0

  • InfiniBand 名称:mlx5_0

  • 网络接口名称:en3f0pf0sf0

注意

此标志是强制性的。

复制
已复制!
            

"device": "03:00.0"

r

representor

DOCA Comch 设备表示器 PCIe 地址

注意

此标志是强制性的。

复制
已复制!
            

"representor": "3b:00.0"

N/A

--cpu

要使用的 CPU 索引。每个 CPU 产生一个数据路径线程。索引从 0 开始。

注意

用户可以多次指定此参数以创建更多线程。

注意

此标志是强制性的。

复制
已复制!
            

"cpu": 6

N/A

--storage-server

用于建立与目标的控制 TCP 连接的 IP 地址和端口。

注意

此标志是强制性的。

复制
已复制!
            

"storage-server": "172.17.0.1:12345"

N/A

--command-channel-name

如果同一设备上存在多个 comch 服务器,则允许自定义用于此应用程序实例的服务器名称。

复制
已复制!
            

"command-channel-name": "storage_zero_copy_comch"


故障排除

有关 DOCA 应用程序的安装或执行中遇到的任何问题,请参阅 DOCA 故障排除

控制线程流程

  1. 解析应用程序参数

    复制
    已复制!
                

    auto const cfg = parse_cli_args(argc, argv);

    1. 准备解析器 (doca_argp_init)。

    2. 注册参数 (doca_argp_param_create)。

    3. 解析参数 (doca_argp_start)。

    4. 销毁解析器 (doca_argp_destroy)。

  2. 显示配置

    复制
    已复制!
                

    print_config(cfg);

  3. 创建应用程序实例

    复制
    已复制!
                

    g_app.reset(storage::zero_copy::make_dpu_application(cfg));

  4. 运行应用程序

    复制
    已复制!
                

    g_app->run()

    1. 查找并打开指定的设备

      复制
      已复制!
                  

      m_dev = storage::common::open_device(m_cfg.device_id);

    2. 查找并打开选定的表示器

      复制
      已复制!
                  

      m_dev_rep = storage::common::open_representor(m_dev, m_cfg.representor_id);

    3. 创建控制路径进度引擎

      复制
      已复制!
                  

      doca_pe_create(&m_ctrl_pe);

    4. 连接到 target_rdma

      复制
      已复制!
                  

      connect_storage_server();

      1. 创建 TCP 套接字。

      2. 连接 TCP 套接字。

    5. 创建 comch 服务器并等待 comch 客户端连接

      复制
      已复制!
                  

      create_comch_server();   while (m_client_connection == nullptr) { static_cast<void>(doca_pe_progress(m_ctrl_pe));   if (m_abort_flag) return; }

    6. 等待配置存储控制消息。

    7. 配置存储

      复制
      已复制!
                  

      configure_storage();

      1. 使用 initiator_comch 提供的导出详细信息创建 mmap。

      2. 导出 mmap 以允许 RDMA 访问。

    8. 将“配置存储”控制消息与重新导出的 mmap 详细信息发送到 target_rdma。

    9. 等待来自 target_rdma 的配置存储控制消息响应。

    10. 向 initiator_comch 发送配置存储控制消息响应。

    11. 等待“启动数据路径”控制消息。

    12. 准备数据路径

      复制
      已复制!
                  

      for (uint32_t ii = 0; ii != m_cfg.cpu_set.size(); ++ii) { prepare_storage_context(ii, msg.correlation_id); }

      1. 创建每个线程的数据上下文

        1. 创建 IO 消息。

        2. 创建进度引擎。

        3. 为 IO 消息缓冲区创建 mmap。

        4. 创建 comch 生产者。

        5. 创建 comch 消费者。

        6. 创建 RDMA 上下文。

        7. 创建 RDMA 连接

          1. 导出 RDMA 连接详细信息 (doca_rdma_export)。

          2. 发送“创建 RDMA 连接”控制消息。

          3. 等待创建 RDMA 连接控制消息。

          4. 使用远程 RDMA 连接详细信息 doca_rdma_connect 启动连接。

      2. 将数据路径控制消息发送到 target_rdma。

      3. 等待来自 target_rdma 的数据路径控制消息响应。

      4. 向 initiator_comch 发送数据路径控制消息响应。

    13. 等待启动存储控制消息。

    14. 验证所有连接是否准备就绪(comch 和 RDMA)

      复制
      已复制!
                  

      wait_for_connections_to_establish();

    15. 向 target_rdma 发送启动存储控制消息。

    16. 创建线程

      复制
      已复制!
                  

      if (op_type == io_message_type::read) { m_thread_contexts[ii].thread = std::thread{&thread_hot_data::non_validated_test, std::addressof(m_thread_contexts[ii].hot_context)}; } else if (op_type == io_message_type::write) { if (m_cfg.validate_writes) { m_thread_contexts[ii].thread = std::thread{&thread_hot_data::validated_test, std::addressof(m_thread_contexts[ii].hot_context)}; } else { m_thread_contexts[ii].thread = std::thread{&thread_hot_data::non_validated_test, std::addressof(m_thread_contexts[ii].hot_context)}; } }

    17. 等待来自 target_rdma 的“启动存储”控制消息响应。

    18. 启动数据路径线程。

    19. 向 initiator_comch 发送启动存储控制消息响应。

    20. 运行所有线程直到完成。

    21. 等待“销毁对象”控制消息。

    22. 向 target_rdma 发送销毁对象控制消息。

    23. 等待来自 target_rdma 的销毁对象控制消息响应。

    24. 销毁数据路径对象。

    25. 向 initiator_comch 发送销毁对象控制消息响应。

  5. 显示统计信息

    复制
    已复制!
                

    printf("+================================================+\n"); printf("| Stats\n"); printf("+================================================+\n"); for (uint32_t ii = 0; ii != stats.size(); ++ii) { printf("| Thread[%u]\n", ii); auto const pe_hit_rate_pct = (static_cast<double>(stats[ii].pe_hit_count) / (static_cast<double>(stats[ii].pe_hit_count) + static_cast<double>(stats[ii].pe_miss_count))) * 100.; printf("| PE hit rate: %2.03lf%% (%lu:%lu)\n", pe_hit_rate_pct, stats[ii].pe_hit_count, stats[ii].pe_miss_count);   printf("+------------------------------------------------+\n"); } printf("+================================================+\n");

  6. 销毁控制路径对象。

性能数据路径线程流程

数据路径涉及尽可能快地轮询 PE;以接收来自 initiator_comch 或 target_rdma 的 IO 消息。

  1. 运行直到 initiator_comch 发送停止 IO 消息

    复制
    已复制!
                

    while (hot_data->running_flag) { doca_pe_progress(pe) ? ++(hot_data->pe_hit_count) : ++(hot_data->pe_miss_count); }

  2. 处理来自 initiator_comch 的 IO 消息

    复制
    已复制!
                

    auto *const hot_data = static_cast<thread_hot_data *>(ctx_user_data.ptr); ... doca_task_submit(static_cast<doca_task *>(task_user_data.ptr));

  3. 处理来自 target_rdma 的 IO 消息

    复制
    已复制!
                

    auto *const hot_data = static_cast<thread_hot_data *>(ctx_user_data.ptr); doca_error_t ret;   auto *const io_message = storage::common::get_buffer_bytes(doca_rdma_task_receive_get_dst_buf(task));   if (io_message_view::get_type(io_message) != io_message_type::stop) { io_message_view::set_type(io_message_type::result, io_message); io_message_view::set_result(DOCA_SUCCESS, io_message); } else { hot_data->app_impl->stop_all_threads(); }   do { ret = doca_task_submit(static_cast<doca_task *>(task_user_data.ptr)); } while (ret == DOCA_ERROR_AGAIN);

  • /opt/mellanox/doca/applications/storage/

© 版权所有 2025 NVIDIA。 上次更新时间:2025 年 2 月 12 日。