仅对英特尔可见 — GUID: xis1520273381539
Ixiasoft
产品终止通知
1. Intel® FPGA SDK for OpenCL™ Pro Edition最佳实践指南介绍
2. 查看您Kernel的report.html文件
3. OpenCL内核设计概念
4. OpenCL内核设计最佳实践
5. 分析(Profiling)您的内核来识别性能瓶颈
6. 提高单个Work-Item内核性能的策略
7. 提高NDRange内核数据处理效率的策略
8. 提高存储器访问效率的策略
9. 优化FPGA面积使用的策略
10. 优化英特尔 Stratix 10 OpenCL设计的策略
11. 提高主机应用程序性能的策略
12. Intel® FPGA SDK for OpenCL™ Pro版最佳实践指南存档
A. Intel® FPGA SDK for OpenCL™ Pro版最佳实践指南修订历史
仅对英特尔可见 — GUID: xis1520273381539
Ixiasoft
10.1.2. 使用单个内核来描述脉动阵列
使用英特尔 Stratix 10 OpenCL设计, Intel® 建议将脉动数组描述成单个内核,对处理单元(PE)使用一个函数,并使用完全展开的循环或嵌套循环来表示数组。
未优化的多内核脉动数组伪码(pseudocode):
// data distribution network over an array of channels channel int c[ROWS][COLS]; channel int d[ROWS][COLS]; attribute((num_compute_units(ROWS,COLS)) kernel void PE() { // get data values from my neighbors while(1){ x = read_channel_intel(c[ROWS-1][COLS]); y = read_channel_inel(d[ROWS][COLS-1]); // some code that uses x and y ... // send the same data values to the next neighbors write_channel_intel(c[ROWS][COLS], x); write_channel_intel(d[ROWS][COLS], y); } }
优化单内核伪码:
kernel void allPEs() { while(1){ int c[ROWS], d[COLS]; #pragma unroll for (int i = 0; i < ROWS; i++) #pragma unroll for (int j = 0; j < COLS; j++) { PE(c[i], d[j]); } } } }
注: PE主体不是内核,而是成为函数调用PE()。展开循环会得到一个PE数组,每个PE都使用2D数组中FPGA的一部分。
根据数组的大小,对于 Intel® FPGA SDK for OpenCL™ Offline Compiler而言,在单个时钟周期内生成为一行或一列数组上所有PE分配相同值c和d的硬件有一定挑战性。这样做也可能会导致fMAX降低。为了解决这个问题,请考虑使用__fpga_reg()函数指示离线编译器在每个新PE的c和d上插入寄存器。 Intel® 建议您仅在知道FPGA上的PE在空间上彼此分离才使用__fpga_reg()函数。
注: __fpga_reg()内置函数是一项高级功能。离线编译器不提供应该在何处插入__fpga_reg()函数调用的相关指导。为了帮助确定是否适合插入__fpga_reg()函数调用,您可以通过实验量化附加寄存器可能对fMAX产生的影响,并检查英特尔 Quartus Prime编译报告。
使用__fpga_reg()函数优化的伪码:
kernel void allPEs() { int c[ROWS], d[COLS]; while(1){ #pragma unroll for (int i = 0; i < ROWS; i++) #pragma unroll for (int j = 0; j < COLS; j++) { // compute and store outputs PE(c[i], d[j]); c[i] = __fpga_reg(c[i]); d[j] = __fpga_reg(d[j]); } } } }
离线编译器展开循环后,在c和d上的每个PE之前有一个寄存器,允许英特尔 Quartus Prime Pro Edition软件将PE分开放置。您也可以通过在代码中插入多个__fpga_reg()调用来添加多个寄存器。例如,调用__fpga_reg(__fpga_reg(x))在数据路径上添加两个寄存器。但是,内核中有过多__fpga_reg()调用会增加设计面积,并且随之产生的拥塞可能会导致fMAX降级。