仅对英特尔可见 — GUID: ewa1456929096307
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: ewa1456929096307
Ixiasoft
6.1.5. 移除由于对存储器阵列的访问而引起的循环依赖
在您的单个work-item内核中包含ivdep pragma,以置位对存储器阵列的访问从而避免导致循环携带依赖项。
编译过程中, Intel® FPGA SDK for OpenCL™ Offline Compiler创建硬件来确保加载和存储指令在依赖约束内运行。依赖项约束的实例,如依赖加载和存储指令必须按顺序执行。有ivdep pragma是为了指示离线编译器在内核代码中的pragma声明之后立即从循环内加载和存储指令之间删除这个额外的硬件。删除该额外硬件可能会降低逻辑利用率并降低单个work-item内核中II的值。
您可以向 ivdep pragma添加safelen(N)子句来提供有关循环依赖关系的更多信息。safelen(N)子句指定没有携带依赖项的循环的连续循环迭代的最大次数。例如,#pragma ivdep safelen(32)向编译器指示在可能引入带有依赖项的循环之前,循环最多有32次迭代。也就是说,虽然#pragma ivdep约定该循环的任何迭代之间没有隐式存储器依赖项,但#pragma safelen(32)约定可能依赖于该迭代,并且最靠近该迭代的那个迭代与该迭代之间相距32次迭代。
- 如果循环内所有到存储器阵列的访问都不会导致循环携带依赖项,则请在以内核代码运行该循环之前添加行#pragma ivdep。
内核代码实例:
// no loop-carried dependencies for A and B array accesses #pragma ivdep for (int i = 0; i < N; i++) { A[i] = A[i - X[i]]; B[i] = B[i - Y[i]]; }
- 要指定对循环内特定存储器阵列的访问不会导致 循环携带依赖项,请在运行您内核代码中的该循环之前添加行#pragma ivdep array (array_name)。
由ivdep pragma指定的阵列必须是局部或者专用存储器阵列,或者是指向专用存储器存储空间的指针变量。如果指定的阵列是一个指针,则ivdep pragma也适用于以指定指针的别名命名的所有阵列。
由ivdep pragma指定的阵列也可以是数组或者结构体的指针部分。
内核代码实例:
// No loop-carried dependencies for A array accesses // The offline compiler will insert hardware that reinforces dependency constraints for B #pragma ivdep array(A) for (int i = 0; i < N; i++) { A[i] = A[i - X[i]]; B[i] = B[i - Y[i]]; } // No loop-carried dependencies for array A inside struct #pragma ivdep array(S.A) for (int i = 0; i < N; i++) { S.A[i] = S.A[i - X[i]]; } // No loop-carried dependencies for array A inside the struct pointed by S #pragma ivdep array(S->X[2][3].A) for (int i = 0; i < N; i++) { S->X[2][3].A[i] = S.A[i - X[i]]; } // No loop-carried dependencies for A and B because ptr aliases // with both arrays int *ptr = select ? A : B; #pragma ivdep array(ptr) for (int i = 0; i < N; i++) { A[i] = A[i - X[i]]; B[i] = B[i - Y[i]]; } // No loop-carried dependencies for A because ptr only aliases with A int *ptr = &A[10]; #pragma ivdep array(ptr) for (int i = 0; i < N; i++) { A[i] = A[i - X[i]]; B[i] = B[i - Y[i]]; }