仅对英特尔可见 — GUID: clp1468865630147
Ixiasoft
仅对英特尔可见 — GUID: clp1468865630147
Ixiasoft
6.2. 循环依赖项(ivdep预处理指令)
ivdep预处理指令告知编译器可以忽略循环迭代之间的存储器依赖关系。忽略依赖关系可节省面积并降低受影响循环的循环启动间隔(II),因为不再需要避免数据冒险(data hazard)的硬件。
您可以将safelen(N)子句添加到ivdep pragma来提供关于循环依赖项的更多信息。safelen(N)子句指定无循环依赖项的连续循环可以迭代的最大次数。例如,#pragma ivdep safelen(32)指示编译器,在引入循环依赖项之前,循环最多可以进行32次迭代。也就是说,#pragma ivdep承诺此循环的任何迭代之间不存在潜在存储器依赖性;与此同时,#pragma safelen(32)承诺距离本次迭代32次迭代远的那个迭代,可能是本迭代的依赖项中与本迭代最靠近的迭代。
- 组件存储器数组
- 指针自变量
- 指向组件存储器的指针可变量
- mm_host对象的引用
用例1:
如果所有到循环内存储器数组的访问都不会导致循环携带依赖项,则请在该循环之前添加#pragma ivdep。
1 // no loop-carried dependencies for A and B array accesses 2 #pragma ivdep 3 for(int i = 0; i < N; i++) { 4 A[i] = A[i + N]; 5 B[i] = B[i + N]; 6 }
用例2:
您可能在特定存储器数组上指定了#pragma ivdep array (array_name),而非所有数组访问。该预处理指令适用于数组、指针或结构体的指针成员。如果指定的数组是指针,则ivdep预处理指令适用于所有可能与指定指针互为别名的数组。
1 // No loop-carried dependencies for A array accesses 2 // Compiler inserts hardware that reinforces dependency constraints for B 3 #pragma ivdep array(A) 4 for(int i = 0; i < N; i++) { 5 A[i] = A[i - X[i]]; 6 B[i] = B[i - Y[i]]; 7 } 8 9 // No loop-carried dependencies for array A inside struct 10 #pragma ivdep array(S.A) 11 for(int i = 0; i < N; i++) { 12 S.A[i] = S.A[i - X[i]]; 13 } 14 15 // No loop-carried dependencies for array A inside the struct pointed by S 16 #pragma ivdep array(S->X[2][3].A) 17 for(int i = 0; i < N; i++) { 18 S->X[2][3].A[i] = S.A[i - X[i]]; 19 } 20 21 // No loop-carried dependencies for A and B because ptr aliases 22 // with both arrays 23 int *ptr = select ? A : B; 24 #pragma ivdep array(ptr) 25 for(int i = 0; i < N; i++) { 26 A[i] = A[i - X[i]]; 27 B[i] = B[i - Y[i]]; 28 } 29 30 // No loop-carried dependencies for A because ptr only aliases with A 31 int *ptr = &A[10]; 32 #pragma ivdep array(ptr) 33 for(int i = 0; i < N; i++) { 34 A[i] = A[i - X[i]]; 35 B[i] = B[i - Y[i]]; 36 }
<quartus_installdir>/hls/examples/tutorials/best_practices/loop_memory_dependency