在软件与 PL 内核之间传输数据 - 2023.2 简体中文

Vitis 统一软件平台文档 应用加速开发 (UG1393)

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 简体中文

在加速器卡或器件中的存储器上传入和传出数据使用的是缓冲器对象 (xrt::bo),这些缓冲器对象是 设置 XRT 管理的内核与内核实参 期间创建的。

类构造函数通常会分配常规 4K 对齐的缓冲器对象。以下代码会创建常规缓冲器对象,其中包含由堆存储器中的用户空间分配的软件应用反向指针,此外还会创建器件侧缓冲器,此缓冲器在与内核实参 (krnl.group_id) 关联的存储体内进行分配。xrt::bo 构造函数中的可选标志允许您创建非标准类型的缓冲器,以供在特殊环境下使用,如创建特殊缓冲器中所述。

std::cout << "Allocate Buffer in Global Memory\n";
auto bo0 = xrt::bo(device, vector_size_bytes, krnl.group_id(0));
auto bo1 = xrt::bo(device, vector_size_bytes, krnl.group_id(1));
auto bo_out = xrt::bo(device, vector_size_bytes, krnl.group_id(2));
重要: 单一缓冲器大小不能超过 4 GB,但为了最大限度提升从主机到全局存储器的吞吐量,AMD 还建议尽可能保留大小至少为 2 MB 的缓冲器。

建立缓冲器并在其中填充数据后,有多种方法可以启用在软件应用与内核之间进行数据传输,如下所述:

使用 xrt::bo::sync()
使用 xrt::bo::sync 通过 XCL_BO_SYNC_TO_DEVICE 标志将数据从主机同步到器件,或者通过 XCL_BO_SYNC_FROM_DEVICE 标志使用 xrt::bo::writexrt::bo::read 将数据从器件同步到主机,以便从主机应用写入缓冲器或者从器件读取缓冲器。
bo0.write(buff_data);
bo0.sync(XCL_BO_SYNC_BO_TO_DEVICE);
bo1.write(buff_data);
bo1.sync(XCL_BO_SYNC_BO_TO_DEVICE);
...
bo_out.sync(XCL_BO_SYNC_BO_FROM_DEVICE);
bo_out.read(buff_data);
注释: 如果按从用户指针创建缓冲器中所述使用用户指针创建了缓冲器,那么执行 xrt::bo::sync 调用足矣,无需 xrt::bo::writexrt::bo::read 命令。
使用 xrt::bo::map()
此方法可将主机侧缓冲器反向指针映射到用户指针。
// Map the contents of the buffer object into host memory
auto bo0_map = bo0.map<int*>();
auto bo1_map = bo1.map<int*>();
auto bo_out_map = bo_out.map<int*>();

后续,软件代码即可为数据读写实践用户指针。但在写入映射的指针之后(或者从映射的指针读取之前),xrt::bo::sync() 命令应搭配所需方向标志用于执行 DMA 操作。

for (int i = 0; i < DATA_SIZE; ++i) {
   bo0_map[i] = i;
   bo1_map[i] = i;
}

// Synchronize buffer content with device side
bo0.sync(XCL_BO_SYNC_BO_TO_DEVICE);
bo1.sync(XCL_BO_SYNC_BO_TO_DEVICE);

XRT 本机 API 还支持其他缓冲器类型和传输场景,如杂项缓冲器中所述。