仅对英特尔可见 — GUID: ewa1397066666833
Ixiasoft
仅对英特尔可见 — GUID: ewa1397066666833
Ixiasoft
1.3. 单个work-item Kernel与NDRange Kernel
当kernel描述单个work-item时, Intel® FPGA SDK for OpenCL™ host可以将kernel作为单个work-item来执行,这就相当于启动一个NDRange大小(1, 1, 1)的kernel。编译器尝试加速单个work-item来获得最佳性能。
OpenCL Specification version 1.0中将这种操作模式描述为task parallel programming(任务并行编程)。task是指通过包含一个work-item的工作组执行kernel。
通常,host并行启动多个work-item。但是,该数据并行编程模型不适用于并行work-item之间必须共享细粒度(fine-grained)数据的情况。该情况下,您可以通过将您的kernel表述为单个work-item来最大化吞吐量。不同于NDRange kernel,单个work-item kernel遵循类似于C编程的自然顺序模型。尤其是您不必对work-item之中的数据分区。
为确保FPGA上高吞吐量单个基于work-item的kernel执行, Intel® FPGA SDK for OpenCL™ Offline Compiler必须在任何给定时间并行处理多个流水线阶段。该并行性(parallelism)是通过流水线化循环的迭代来实现。
请参考如下简单实例代码,它显示为单个work-item的累加:
1 kernel void accum_swg (global int* a, global int* c, int size, int k_size) { 2 int sum[1024]; 3 for (int k = 0; k < k_size; ++k) { 4 for (int i = 0; i < size; ++i) { 5 int j = k * size + i; 6 sum[k] += __prefetching_load(&a[j]); 7 } 8 } 9 for (int k = 0; k < k_size; ++k) { 10 c[k] = sum[k]; 11 } 12 }

下图说明i的每次迭代如何进入块:
您在观察外部循环时会看到,II值为1也意味着线程的每次迭代可在每个时钟周期进入。在本实例中,认为k_size为20和size为4。这样对于首8个时钟周期来说是正确的,因为外部循环迭代0到7可以进入,而且无任何下游(downstream)中止它。一旦 线程0进入内部循环,它需要4次迭代才能完成。线程1到8无法进入内部循环,并且它们会被线程0停顿4个周期。线程1在线程0的迭代完成后才进入内部循环。因此, 线程9在时钟周期13进入外循环。线程9到20每四个时钟周期进入循环, 这个由size的值决定。通过该实例,您可以观察到外循环的动态启动间隔大于静态预测的启动间隔1,并且它是内循环的行程计数的函数。

- 使用以下函数中的任意一个会导致您的kernel被解释为NDRange:
- get_local_id()
- get_global_id()
- get_group_id()
- get_local_linear_id()
- barrier
- 如果reqd_work_group_size属性被指定成(1, 1, 1)以外的任何值,您的kernel就将被解释成NDRange。否则,您的kernel将被解释为single-work-item kernel。
请考虑用同一累加实例编写的NDRange:
kernel void accum_ndr (global int* a, global int* c, int size) { int k = get_global_id(0); int sum[1024]; for (int i = 0; i < size; ++i) { int j = k * size + i; sum[k] += a[j]; } c[k] = sum[k]; }

限制
OpenCL任务并行编程模型不支持notion笔记中single-work-item执行中的barrier。请使用memory fence(mem_fence)替代您内核中的barrier(barrier)