Intel®高层次综合编译器专业版: 最佳实践指南

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

5.4. 最小化循环携带的依赖性

当循环迭代中的代码依赖于之前循环迭代的输出时,就产生携带依赖关系的循环。您组件中携带依赖关系的循环会增加循环启动间隔(II),从而降低组件性能。

因为每个循环迭代读取之前迭代写入的数据,以下循环结构有循环携带依赖关系。这样,直到前一次迭代的写操作完成后,才能继续执行每个读操作。循环携带的依赖关系的存在会减少 Intel® HLS Compiler Pro Edition可达到的流水线化并行度,从而降低组件性能。

for(int i = 1; i < N; i++)
{
    A[i] = A[i - 1] + i;
}

Intel® HLS Compiler Pro Edition对循环执行静态存储器依赖性分析以确定其当前可达到的流水线并行度。如果 Intel® HLS Compiler Pro Edition无法确定是否存在循环携带依赖关系,则假定存在循环依赖关系。编译时的未知变量或代码中设计复杂寻址的数组访问都会阻碍编译器检测循环携带依赖性的能力。

为了避免不必要的循环携带依赖关系,并帮助编译器更好的分析循环,请遵照以下指导:

避免指针运算

当组件通过解除引用算术运算获得的指针值来访问数组时,编译器输出将仅为次优。例如,避免如以下方式访问数组:

for(int i = 0; i < N; i++)
{
    int t = *(A++);
    *A = t;
}

引入简单数组索引

复杂数组索引的某些类型无法被有效分析,进而可能导致不太好的编译器输出。尽可能避免如下构造:
  • 数组索引中的非常量。

    例如,A[K + i],其中i是循环索引变量,以及K是未知变量。

  • 相同下标位置中的多索引变量。

    例如,A[i + 2 × j],其中ij是双嵌套循环的循环索引变量。

    可有效分析数组索引A[i][j]是因为索引变量位于不同下标位置。

  • 非线性索引。

    例如,A[i & C],其中i是循环索引变量,而C是非常量。

尽可能使用带Constant Bound的循环

当循环中有constant bound时编译器可有效执行范围分析。

可在循环中放置一个if-statement以控制迭代循环主体在哪个迭代中执行。

忽略存储器依赖关系

如果循环迭代中无隐含的存储器依赖关系,就可使用ivdep pragma指令告诉 Intel® HLS Compiler Pro Edition忽略可能存在的存储器依赖关系。

有关如何使用ivdep预处理指令的详细信息,请参阅 Intel® High Level Synthesis Compiler Pro版参考手册中的循环携带的依赖关系(ivdep Pragma)部分。