Intel® 高层次综合编译器专业版Pro版: 参考手册

ID 683349
日期 12/04/2023
Public
文档目录

13.7. Intel® HLS Compiler Pro版循环预处理指令

使用 Intel® HLS Compiler循环预处理指令控制编译器如何对组件中的循环进行流水线处理。

表 43.   Intel® HLS Compiler Pro版循环预处理指令总结
预处理指令 描述
disable_loop_pipelining 防止编译器将循环流水线化,
ii 强制循环具有指定值的循环启动间隔(II)。
ivdep 忽略此循环的迭代之间的存储器依赖关系。
loop_coalesce 尝试将嵌套在此循环内的所有循环融合为单个循环。
loop_fuse 指示编译器尝试将相邻的循环融合成对。
max_concurrency 对于随时都能同时执行的循环,将限制其迭代次数。
max_interleaving 控制内循环的一次调用中嵌套循环的流水线内循环迭代是否可以与内循环中其它调用的迭代在组件数据流水线中交错进行。
nofusion 防止带注释的循环与相邻的循环融合。
speculated_iterations 指定计算循环退出条件可用于计算的时钟周期数。
unroll 完全展开循环或者按一定次数展开循环。

disable_loop_pipelining循环预处理指令

句法
#pragma disable_loop_pipelining
描述
告知编译器不要对该循环进行流水线处理。

当循环携带依赖性使得循环迭代有效地按顺序执行时,请禁用循环的循环流水线。禁用循环流水线后, Intel® HLS Compiler可以生成更简单的数据路径并减少您组件的FPGA面积利用率。

实例:
#pragma disable_loop_pipelining
for (int i = 1; i < N; i++) {
    int j = a[i-1];
    // Memory dependency induces a high-latency loop feedback path
    a[i] = foo(j)
}

ii循环预处理指令

句法
#pragma ii N
描述
强制应用此指令的循环具有循环启动间隔 (II) <N>,其中<N>是一个正整数值。

强制循环II值可能会对您组件的fMAX产生不利影响,因为使用此指令来获得较低的循环II会将管道阶段组合在一起并创建具有长传播延迟的逻辑。

将此指令与更大的循环II一起使用时会插入更多流水线阶段,并能为您提供更好的组件fMAX值。

实例:
#pragma ii 2
for (int i = 0; i < 8; i++) {
 // Loop body
}

ivdep循环预处理指令

句法
#pragma ivdep safelen(N) array(array_name)
描述
告知编译器忽略此循环迭代之间的存储依赖关系。

它可以接受指定数组名称的可选参数。如果未指定array,则忽略所有组件存储依赖性。如果存在循环携带依赖性,则生成的RTL会产生不正确的结果。

safelen参数指定依赖关系的距离。依赖关系的距离是相互依赖的连续加载/存储之间的迭代次数。只有在依赖关系距离为无限远(即,没有真正的依赖关系)的情况下,不包含safelen也安全。

实例:
#pragma ivdep safelen(2)
for (int i = 0; i < 8; i++) {
 // Loop body
}

To learn more, review the tutorial: <quartus_installdir>/hls/examples/tutorials/best_practices/loop_memory_dependency

loop_coalesce循环预处理指令

句法
#pragma loop_coalesce N
描述
告知编译器尝试将此循环内嵌套的所有循环融合为单个循环。此指令接受可选值N,该值表示要合并在一起的循环级别数
#pragma loop_coalesce 2
for (int i = 0; i < 8; i++) {
 for (int j = 0; j < 8; j++) {
 // Loop body 
 } 
}

loop_fuse模块范围的循环预处理指令

句法
#pragma loop_fuse [depth(N)] [independent]
描述
将此指令应用于代码的模块,以向编译器指示代码块中相邻的循环应该在安全的情况下进行融合,从而覆盖编译器对融合的盈利性分析。

depth(N)子句设置融合相邻循环期间编译器应考虑的嵌套深度数。指定depth(1)相当于表明只应考虑相邻的顶层循环进行融合。

independent子句会覆盖安全性检查。如果您指定independent选项,等于向编译器保证, 受loop_fuse指令的影响而融合的循环对安全的。如果它不安全,则您的组件中可能会出现功能错误。

关于安全检查的详细信息,请参阅循环融合(Loop Fusion)Fusion Criteria部分。

实例:

#pragma loop_fuse
{
 for (int j=0; j < N; ++j){
   data[j] += Q;
 }
 for (int i = 0; i < N; ++l){
   output[i] = Q * data[i];
 }
 }

max_concurrency循环预处理指令

句法
#pragma max_concurrency N
描述
此指令限制了随时可同时执行的循环迭代次数。

此指令主要用于创建专用副本以提高循环的吞吐量。Loop Analysis窗格下关于该循环的的详细信息窗格中,以及在高层次设计报告(report.html)的Function Memory Viewer下的Bank视图中都提到了该情况。

仅当组件存储器的范围(通过其声明或访问模式)仅限于此循环时才会发生这种情况。添加此指令可用于减少循环消耗的区域,但会牺牲一定的吞吐量。

实例:
// Without this pragma,
// multiple private copies 
// of the array "arr"
#pragma max_concurrency 1
for (int i = 0; i < 8; i++) {
 int arr[1024];
 // Loop body
}

max_interleaving循环预处理指令

句法
#pragma max_interleaving <option>
描述<option>
该指令控制内循环一次调用后的循环嵌套中流水线化内循环的迭代是否能够在组件数据管道中与其他内循环调用的迭代交错进行。

默认情况下, Intel® HLS Compiler尝试多次交错执行一些内循环的同步调用,该次数等于内循环的循环启动间隔 (II)。例如,II为2的内循环可以在管道中同时进行两次调用的迭代。

从不同循环调用的循环迭代交错进行并未带来性能优势的情况下,限制或约束交错量可能会导致FPGA面积利用率降低。

支持的值<option>
  • 1

    编译器限制注释的(内部)循环在每个外部循环迭代中仅被调用一次。换言之,内部循环的所有迭代都会在管道中执行,之后才能调用下一次内部循环。

  • 0

    使用默认的交错行为。

实例:
// Loop j is pipelined with ii=1
for (int j = 0; j < M; j++) {
  int a[N];
  // Loop i is pipelined with ii=2 
  #pragma max_interleaving 1
  for (int i = 1; i < N; i++) {
      a[i] = foo(i)
  }
  …
}

nofusion循环预处理指令

句法
#pragma nofusion
描述
该指令指示编译器不要将带注释的循环与任何相邻的循环融合。
实例:
#pragma nofusion
L1: for (int j=0; j < N; ++j){
 data[j] += Q;
}
L2: for (int i = 0; i < N; ++l) {
 output[i] = Q * data[i];
}

speculated_iterations循环预处理指令

句法
#pragma speculated_iterations N
描述
此指令指定在考虑循环退出条件之前要等待的循环迭代次数。也就是说,您估计循环至少需要N个循环迭代直到满足退出条件。

如果指定的值太低,则会因为顾及需要的迭代,循环II会增加,从而确定循环退出条件是否满足所需的迭代次数。

实例:

component int loop_speculate (int N) {
    int m = 0;
    // The exit path has 2 multiplies and 
    // compare is most critical in loop feedback path
    #pragma speculated_iterations 2
    while (m*m*m < N) {
      m += 1;
    }
    return m;
  }

unroll循环预处理指令

句法
#pragma unroll N
描述
此指令完全展开循环,或者通过<N>次,其中<N>是可选的,并且是一个正整数值。
重要: 展开具有较大边界的嵌套循环可能会导致组件的编译时间非常长。
实例:
#pragma unroll 8
for (int i = 0; i < 8; i++) {
 // Loop body
}

要了解更多详细信息,请查看教程: <quartus_installdir>/hls/examples/best_practices/resource_sharing_filter.