65.9K
CodeProject 正在变化。 阅读更多。
Home

超越直接内存访问:使用 Intel Data Streaming Accelerator 降低数据中心开销

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.80/5 (2投票s)

2023 年 12 月 18 日

CPOL

10分钟阅读

viewsIcon

3549

利用第四代 Intel® Xeon® 可扩展处理器上的片上加速实现数据转换

在现代数据中心中,我们已经看到了广泛的涉及密集内存操作和转换的应用程序,例如 memcpy()memmove()、哈希和压缩。这些应用程序包括但不限于数据库、图像处理和视频传输以及图处理。此外,此类内存操作和转换在数据中心的基础设施软件中也很常见,消耗了大量的 CPU 周期。这也被称为“数据中心税”,因为这些周期本可以用于运行应用程序。理想情况下,此类操作应卸载到优化的硬件引擎。

英特尔® 数据流加速器

英特尔数据流加速器 (Intel® DSA) 是集成在最新第四代英特尔® 至强® 可扩展处理器中的高性能数据复制和转换加速器。它不仅提供处理效率和实用性,还提供多功能性。Intel DSA 配备了硬件组件,可高效处理一个或多个用户提交的工作描述符。通过共享虚拟内存 (SVM) 的支持,这些工作描述符可以通过内存映射 I/O (MMIO) 寄存器由用户应用程序直接提交给 Intel DSA,并且目标内存区域无需在操作系统中固定。用户还可以根据自身需求直接配置底层计算资源,这得益于一组专用驱动程序提供的用户界面。此外,Intel DSA 通过新支持的操作提供了更好的功能(表 1)。因此,预计更多的用户/内核进程可以利用 Intel DSA 提供的功能。

表 1. 英特尔® DSA 支持的数据流操作

英特尔® 数据加速器驱动程序 (IDXD) 是用于设备初始化和管理的内核模式驱动程序。它提供 Intel DSA 发现、初始化和配置功能。应用程序可以利用用户空间的 libaccel-config API 库进行此类控制操作。对于数据路径,为了为应用程序提供对 Intel DSA 实例的低延迟访问,IDXD 通过 mmap() 将 MMIO 门户公开为 char 设备。鉴于所有这些新功能和改进,我们看到 Intel DSA 在多个领域(表 2)和多个操作上相对于其软件对应物实现了显著的性能提升,尤其是对于中到大数据量(图 1)。

Area

示例应用程序和操作

网络堆栈加速

DPDK、软件虚拟交换机、视频传输

存储堆栈加速

SPDK、NVMe-oF、DAOS

数据中心税减免

虚拟机启动/迁移、内存压缩

HPC/ML 加速

libfabric/MPI 中的内存移动/归零

异构内存管理加速

CXL/Pmem 分层内存系统的页面迁移

表 2. Intel® DSA 在多个领域的潜在用途

图 1. 数据流操作相对于其软件对应物在不同传输大小(批次大小:1)下的吞吐量改进;内存填充和 NT-内存填充分别指分配式写入和非分配式写入(类似于常规存储和 NT-存储)

操作 Intel DSA

与其他加速器一样,Intel DSA 采用描述符和工作队列 (WQ) 与 CPU 软件进行交互(图 2)。

图 2. 描述符处理序列

数据移动是 Intel DSA 最常见的用例,因此我们将使用数据复制示例来演示其用法。假设在一个键值存储应用程序中,我们有较大的键值对大小,每次我们检索或更新给定键的值时,都会发生内存复制并消耗大量的 CPU 周期。我们宁愿将这些操作卸载到 Intel DSA。假设 Intel DSA 实例已经通过 accel-config 等工具枚举和配置,程序员首先需要分配并填充描述符数据结构(图 3)。描述符包含有关所需操作的信息,例如操作类型、源和目标地址、数据长度等。

struct dsa_completion_record comp_attribute_((aligned(32)));

struct dsa_hw_desc desc = { };

desc.opcode = DSA_OPCODE_MEMMOVE;

/*
 * Request a completion - since we poll on status, this flag
 * must be 1 for status to be updated on successful
 * completion
 */
desc.flags = IDXD_OP_FLAG_RCRl

/* CRAVE should be 1 since RCR = 1 */
desc.flags |= IDXD_OP_FLAG_CRAV;

/* Hint to direct data writes to CPU cache */
desc.flags |= IDXD_OP_FLAG_CC;

desc.xfer_size = BLEN;
desc.src_addr = (unintptr_t)src;
desc.src_addr = (unintptr_t)dst;
comp.status = 0;
desc.completion_addr = (uintptr_t)∁
图 3. 描述符初始化

准备好描述符后,程序员的下一步是将描述符提交到当前程序中打开和映射的 WQ。根据 WQ 类型,软件可以使用 ENQCMDMOVDIR64B 指令进行描述符提交。这两种指令都受 GNU GCC(版本 10 及更高版本)支持,程序员可以使用 x86 内联函数来调用它们(图 4)。

#include <x86printrin.h>

_mm_sfence();

if (dedicated)
    _movdir64b(wq_portal, &desc);
else {
    retry = 0;
    while (_enqcmd(wq_portal, &desc) && retry++ < ENQ_RETRY_MAX);
}
图 4. 描述符提交

为了检查描述符的完成情况,程序员需要轮询完成记录的状态字段,该字段将由 Intel DSA 更新。最常见的方法是自旋轮询(图 5)。新指令,例如 PAUSEUMONITOR/UMWAIT,可以用于进一步降低处理器的功耗,因为核心可以通过这些指令进入不同的功耗状态。(有关更多信息,请参阅 英特尔® 64 和 IA-32 架构软件开发人员手册。)

retry = 0;
while (comp.status == 0 && retry++ < COMP_RETRY_MAX);

if (comp.status == DSA_COMP_SUCCESS) {
    /* Successful completion */
} else {
    /* Descriptor failed or timed out
     * See the "Error Codes" section of the Intel® DSA Architecture Specificatio nfor
     * error code descriptions
     */
}
图 5. 检查描述符完成情况

利用软件库利用 Intel DSA

英特尔® 数据移动器库 (Intel® DML) 和英特尔® DSA 透明卸载库 (Intel® DTO) 使 Intel DSA 更易于使用。Intel DML 提供了一组用于数据移动和转换的高级 C/C++ API,在可用时调用底层的 Intel DSA 单元。它支持高级功能(所有 Intel DSA 硬件操作、异步卸载、负载平衡等)。Intel DML v1.0.0 可在 GitHub 上获取。克隆仓库并安装所需的包后,可以通过简单的 CMake 命令编译和安装(有关更多安装选项,请参阅 Intel DML 文档

Windows* 操作系统

mkdir build
cd cuild
cmake -DCMAKE_INSTALL_PREFIX=<install_dir> -G "NMake Makefiles" ..
cmake --build . --target install

Linux* 操作系统

mkdir build
cd cuild
cmake -DCMAKE_INSTALL_PREFIX=<install_dir> ..
cmake --build . --target install

图 6 展示了 Intel DML 的基本用法。虽然基本步骤保持不变,但更多细节被 Intel DML API 和抽象所隐藏。继续以 key-value 存储应用程序为例,程序员无需手动准备和提交描述符,而是可以调用 Intel DML,从而将指定的内存复制卸载到 Intel DSA。

#include <dml/dml.hpp>
#include <numberic>
#include <vector>
#include <iostream>

constexpr auto size = 1024u; // 1 KB

template <typename path>
int execute_mem_move() {
    std::cout << "Starting dml::mem_move example..." << std::endl;
    std::cout << "Copy 1KB of data from source into destination..." << std::endl;

    // Prepare data
    auto src = std::vector<std::uint>(size);
    std::iota(src.begin(), src.end(), 0u);
    auto dst = std::vector<std::unit8_t>(size, 0u);

    // Run operation
    auto result == dml::execute<path>(dml::mem_move, dml:make_view(src), dml::make_view(dst));

    // Check result
    if (result.status == dml::status_code::ok) {
        std::cout << "Finished successfully." << std::endl;
    }
    else {
        std::cout << "Failure occurred." << std::endl;
        return -1;
    }

    if (src != dst) {
        std::cout << "Operation result is incorrect" << std::endl;
        return -1;
    }
   
    return 0;
}
图 6. 使用 Intel® DML 进行基本数据移动的示例

Intel DTO 是一个侵入性较小的库,允许应用程序透明地利用 Intel DSA,而无需修改源代码。用户可以通过使用 ‑ldto‑laccel‑config 链接器选项动态链接库,或者通过 LD_PRELOAD 预加载库,而无需重新编译其应用程序。当使用 memmove()memcpy()memset()memcmp() 等常见系统 API 调用时,它们会被 Intel DTO 函数拦截并替换,以访问相应的同步 Intel DSA 操作。

除了 Intel DML 和 Intel DTO(通用库)之外,还有利用 Intel DSA 的特定领域软件库。例如,在用于高性能内核旁路网络编程的数据平面开发套件 (DPDK) 中,Intel DSA 与其他供应商的 DMA 引擎一起被抽象和封装在 dmadev 库中。用户可以调用相应的 API 将网络数据包复制卸载到 Intel DSA 实例。同样,存储性能开发套件 (SPDK) 在其 /lib/accel 库中支持 Intel DSA,以支持各种操作卸载。Intel DSA 也已在 HPC 库中启用,例如 libfabricMPI,这些库不仅用于传统的科学计算工作负载,还用于新兴的分布式 ML/AI 应用程序。

充分利用 Intel DSA

作为用于流数据的片上加速器,Intel DSA 得益于对编程模型进行适当的调优以实现最佳性能。根据我们的经验,我们总结了一些使用 Intel DSA 的指南和建议。(有关更多详细信息,请参阅此 技术报告。)

保持批处理大小和传输大小平衡

将一定大小的工作卸载到 Intel DSA 可以通过使用一个描述符处理整个内存区域,或者批处理多个较小的描述符以实现相同的聚合大小来完成。一般趋势表明,当使用较大的批次处理相同的卸载工作时,吞吐量会下降。由于单个描述符必须在 Intel DSA 内部处理并从内存中读取相应的数据,因此管理增加的描述符数量所带来的额外开销可能会降低这些操作的有效吞吐量。如果需要卸载的数据是连续的,将其合并为一个等效大小的较大单个描述符可能会提高吞吐量和延迟。

同步卸载时,出现了一个微弱的模式,表明在最大化批处理和最大化传输大小之间存在一个最佳吞吐量点。适度批处理工作(4-8 个描述符)可获得最佳结果。这是因为平衡了从顺序内存区域获取数据和处理批处理描述符的延迟。

尽可能异步使用 Intel DSA

以异步方式将操作卸载到 Intel DSA 可为 CPU 核心和 Intel DSA 硬件提供最佳效率和性能。这可以使用 Intel DML 轻松实现。当异步潜力有限时,如果缓存污染可以接受,则应在 CPU 核心上使用小于 4 KB 的传输大小。作为片上加速器,Intel DSA 提供了更多与缓存和(异构)内存层次结构交互的选项。

明智地控制数据目的地

与始终定向到 LLC 的完成记录不同,写入描述符目标地址的数据可以导向 LLC 或主内存。Intel DSA 通过允许用户提供提示(即设置工作描述符的缓存控制标志)来指出首选目的地,从而实现此缓存控制功能。如果标志设置为 0,则数据写入内存,同时使 LLC 中相应的缓存行(如果有)失效。如果标志设置为 1,则通过分配相应的缓存行直接将数据写入 LLC。此技术的基本原理与 Intel® 数据直接 I/O 技术 (Intel® DDIO) 相同,DDIO 是一种直接缓存访问 (DCA) 方案,利用 LLC 作为处理器和 I/O 设备之间的中间缓冲区。通常,DDIO 通过减少数据访问延迟和降低内存带宽压力来提高系统性能。但是,在使用此功能时应小心,因为它有时会导致 LLC 中出现干扰。

缓存污染会对共享有限硬件资源的过程产生负面影响。在许多数据中心工作负载中,对抗性后台缓存逐出所带来的延迟可能会削弱为主应用程序设定的竞争性服务水平协议 (SLA)。另一方面,将对性能至关重要或核心在不久的将来使用的数据直接写入缓存将为应用程序提供访问延迟和吞吐量优势。程序员应根据应用程序行为明智地选择数据目的地。

Intel DSA 作为跨异构内存系统移动数据的良好选择

在现代分层内存系统中,将数据移动到/从不同内存介质(例如 NUMA 远程内存、持久内存和基于 CXL 的内存)是很常见的。Intel DSA 通过可用的硬件资源提供高度的配置灵活性。利用此类配置可以实现最佳的 Intel DSA 硬件利用率,从而获得更好的性能。

利用处理引擎级并行性

组中使用的处理引擎数量可能会影响观察到的最大吞吐量。增加每组的处理引擎数量会提高吞吐量。用户应该了解卸载到这些组的任务的常见传输大小,因为较小的传输大小会产生更大的性能扩展。

优化 WQ 配置

与共享 WQ (SWQ) 相比,使用批处理或专用 WQ (DWQ) 可提供更大的好处。除非共享 WQ 被许多其他线程使用,否则通过重新配置以使用更多 DWQ 可以实现更高的利用率和吞吐量。当使用少量线程时,SWQ 的性能可能更差,但当使用的线程多于 WQ 总数时,它可以超越所有配置,因为这将并发管理卸载到硬件。此外,WQ 可以配置为共享或专用,以在组内的 WQ 之间提供性能隔离。由于 Intel DSA 的 WQ 条目有限,为单个 WQ 分配 32 个条目可以提供几乎最大的吞吐量。

结论

Intel DSA 以及出现在第四代英特尔至强可扩展处理器中的其他片上加速器,有潜力降低数据中心税和总拥有成本。本文对 Intel DSA 及其基本用法进行了高级概述,并提供了一些充分利用此加速器的指南。随着软件生态系统的不断发展,我们相信 Intel DSA 将被用于许多数据中心工作负载。英特尔一直积极与开源社区合作,构建和赋能这个生态系统。

其他资源

© . All rights reserved.