仅对英特尔可见 — GUID: mwh1391807502532
Ixiasoft
仅对英特尔可见 — GUID: mwh1391807502532
Ixiasoft
7.2. 内核矢量化
在您的内核代码中包含num_simd_work_items属性以指示离线编译器在不修改内核主题的情况下对每个work-item执行更多加法。以下代码片段将向量化因子4应用于原始内核代码:
__attribute__((num_simd_work_items(4))) __attribute__((reqd_work_group_size(64,1,1))) __kernel void sum (__global const float * restrict a, __global const float * restrict b, __global float * restrict answer) { size_t gid = get_global_id(0); answer[gid] = a[gid] + b[gid]; }
要使用num_simd_work_items属性,您还必须使用reqd_work_group_size属性指定需要的工作组大小。您对reqd_work_group_size指定的工作组大小必须能被您分配给num_simd_work_items的值整除。在上述代码实例中,内核具有64个work-item的固定工作组大小。在每个工作组内,work-item平均分布在4个SIMD矢量lane中。在离线编译器实现四个SIMD矢量lane后,每个work-item现在执行四倍的工作。
离线编译器矢量化代码,并且可能合并存储器访问。您不需要更改任何内核代码或者主机代码,因为离线编译器会自动应用这些优化。
可以手动矢量化您的内核代码,但是必须调整您主机应用程序中的NDRange以反映您实现的矢量化程度。如下实例显示了手动复制内核中的操作时代码的变更情况:
__kernel void sum (__global const float * restrict a, __global const float * restrict b, __global float * restrict answer) { size_t gid = get_global_id(0); answer[gid * 4 + 0] = a[gid * 4 + 0] + b[gid * 4 + 0]; answer[gid * 4 + 1] = a[gid * 4 + 1] + b[gid * 4 + 1]; answer[gid * 4 + 2] = a[gid * 4 + 2] + b[gid * 4 + 2]; answer[gid * 4 + 3] = a[gid * 4 + 3] + b[gid * 4 + 3]; }
该形式下,内核加载从数组a和b来的四个单元,计算求和,并将计算结果存储到数组answer中。因为FPGA流水线加载并将数据加载到存储器中的相邻位置,您可以手动指示离线编译器来合并每组四个加载和存储应用操作。