Intel® FPGA SDK for OpenCL™ Pro Edition: 最佳实践实践指南

ID 683521
日期 9/26/2022
Public
文档目录

3.4.2. 循环携带的依赖项影响了循环的启动间隔

某些情况下,即使循环已经流水线化,但却没有达到II值为1。这些情况通常是由循环内的数据依赖项或者存储器依赖项所造成。

数据依赖项

数据依赖项是指循环迭代使用的变量依赖于前一次迭代。该情况下,即使循环已流水线化,但是其II值可能大于1。请参考如下实例:

1  // An example that shows data dependency
 2  // choose(n, k) = n! / (k! * (n-k)!)
 3
 4  kernel void choose( unsigned n, unsigned k, 
 5                      global unsigned* restrict result )
 6  {
 7      unsigned product = 1;
 8      unsigned j = 1;
 9
10      for( unsigned i = k; i <= n; i++ ) {
11          product *= i;
12          if( j <= n-k ) {
13              product /= j;
14          }
15          j++;
16      }
17
18      *result = product;
19  }

对于每次循环迭代, 内核chooseproduct 变量的值是通过将索引i的当前值乘以前一次迭代的product值计算而来。因此,在当前迭代完成处理之前,无法启动循环的新迭代。

内核choose中循环的启动间隔(II)的值为12。可在Loop Analysis报告中找到该值。此外,下图中的详情窗格中显示,高II值是由于对product的数据依赖而造成,并且主要是关键路径上第13行的整除触发运算所导致。

图 56. 内核choose的Loop Analysis Report中的Details Pane(详情窗格)

存储器依赖项

存储器依赖是指循环迭代中的存储器访问无法在前一次循环迭代完成之前进行。请参考以下实例:

1  kernel void mirror_content( unsigned max_i,
2                              global int* restrict out)
3  {
4    for (int i = 1; i < max_i; i++) {
5      out[max_i*2-i] = out[i];
6    }
7  }

在循环分析报告中,详情窗个中显示,该存储器依赖位于第5行上两个加载和存储操作之间,并且该加载操作需要202个时钟周期。

图 58. 内核mirror_content的Loop Analysis Report中的Details Pane(详情窗格)