FPGA开发中如何让主机与内核数据存储在不同内存空间
问题1:host与FPGA端内存分离的原因
- FPGA属于异构计算设备,和CPU的物理内存硬件上相互独立,不存在默认的共享地址映射,直接访问对方内存会触发总线错误,这是硬件层面的天然限制
- 分离内存可以避免host端的非法操作意外篡改FPGA kernel运行时的寄存器、缓存或者缓冲区数据,降低运行时崩溃、计算结果错误的概率
- 主流FPGA异构开发框架(比如Xilinx Vitis、Intel OpenCL for FPGA)的编程模型本身就要求显式管理两端内存,隐式共享内存的逻辑在这类框架下不被支持,不符合开发规范
问题2:通过指针管理不同内存空间的实现逻辑
- host端的普通指针指向CPU内存地址空间,你需要调用FPGA开发框架提供的内存分配接口(比如Vitis的
clCreateBuffer、XRT的xrtBOAlloc)申请FPGA端的内存,这类接口返回的缓冲区句柄或者设备指针,仅用于在host端标识FPGA内存块,不能直接在host侧解引用读写 - 数据传输需要调用框架提供的显式拷贝接口(比如
clEnqueueWriteBuffer),在host指针指向的CPU内存和设备指针指向的FPGA内存之间做数据同步 - 所有FPGA kernel的入参都传设备指针,host侧的运算、预处理仅操作host指针指向的CPU内存,两者完全隔离
问题3:现有数组转指针形式的实现代码
你原有栈分配数组可以保留作为host侧的数据源,显式转换为指针形式或者改用堆分配指针的示例如下:
// 方案1:对原有栈数组做显式指针转换,访问逻辑完全兼容原有写法 int (*host_array_X_set)[20] = array_X_set; // 指向二维数组的指针 int *host_array_Y_set = array_Y_set; int (*host_X_train)[20] = X_train; int *host_Y_train = Y_train; int (*host_X_test)[20] = X_test; int *host_Y_test = Y_test; // 原有赋值逻辑可以保持不变,也可以用上述指针操作 for (int i = 0; i < 5430; i++) { for (int j = 0; j < 20; j++) host_array_X_set[i][j] = array_X_dataset[i][j]; host_array_Y_set[i] = array_Y_dataset[i]; } // 方案2:改用堆分配host指针,避免大数组占用栈空间导致溢出 int (*host_array_X_set)[20] = malloc(sizeof(int) * 5430 * 20); int *host_array_Y_set = malloc(sizeof(int) * 5430); int (*host_X_train)[20] = calloc(4344 * 20, sizeof(int)); // calloc自动初始化为0 int *host_Y_train = calloc(4344, sizeof(int)); int (*host_X_test)[20] = calloc(1086 * 20, sizeof(int)); int *host_Y_test = calloc(1086, sizeof(int)); // 赋值、读写逻辑和原写法完全一致,使用完成后需调用free释放堆内存
上述host_前缀的指针仅用于CPU侧操作,FPGA侧的设备指针需要结合你使用的开发框架调用对应API申请,不要和host指针混用。
内容的提问来源于stack exchange,提问作者user16767585
相关产品推荐
相关产品推荐

