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

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

6.9. 循环融合(Loop Fusion)

循环融合是一种编译器转换,其中两个相邻的循环在同一索引范围内合并成单个循环。这种转换通常用于减少循环开销并提高运行时性能。

如下实例显示了在简单情况下融合循环的效果:
Unfused Loops Fused Loop
for (j = 0; j < 300; j++)
    a[j] = a[j] + 3;
for (k = 0; k < 300; k++)
    b[k] = b[k] + 4;
for (f = 0; f < 300; f++) {
    a[f] = a[f] + 3;
    b[f] = b[f] + 4;
}
以下示例显示了在并置的循环索引范围内融合循环的效果:
Unfused Loops Fused Loop
for (j = 0; j < 300; j++)
a[j] = a[j] + 3;
for (k = 0; k < 300; k++)
b[k] = b[k] + 4;
for (jk = 0; jk < 600; jk++)
{
    if (jk < 300)
    { 
        int j = jk;
        a[j] = a[j] + 3;
    } else 
    {
        int k = jk - 300;
        b[k] = b[k] + 4;
    }
}

循环控制结构意味着很大的开销。通过融合两个循环,循环所需要的控制结构的数量就从两个减少到一个,从而减少了此开销。减少该控制结构数量的主要目的是为您的设计节省FPGA的面积的同时,仍然保持(理想情况下增加)组件吞吐量。

融合外部循环会引入并行出现过的并发性。将两个相邻的循环(Lj和Lk)主体合并起来形成单个循环(Lf),其中的循环主体包含Lj和Lk主体。该组合循环主体可实现Lj和Lk的给定迭代串行化以并行执行的操作。实际上,这两个循环现在是作为单循环以锁步(lockstep)方式执行,从而改善了延迟情况。

如果融合了内部循环,而外部循环迭代的流水线执行已经实现了该并行性。该情况下,循环融合的并行效果就会减弱。

融合条件

如果Lj和Lk满足如下条件,则编译器认为这两个循环的融合有效:
  • 两个循环必须相邻。

    也就是说,您不能有一个带有副作用的声明Si,使得Lj之后先执行Si,然后才执行Lk

  • 每个循环必须有一个single-entry point(单一入口点)和一个single exit point(单一出口点)。

    例如,不考虑融合包含break声明的循环。

  • 循环必须没有负距离(negative-distance)依赖项。

    也就是说,对于Lj先于Lk被定义的Lj和Lk中,循环Lk的迭代m不依赖于循环Lj的迭代m+n(其中n>0)中计算的值。

自动循环融合(Loop Fusion)

如果您组件的编译器分析确定融合循环是有益的,则 Intel® HLS Compiler自动相邻融合具有相同行程计数的循环。

循环融合有效转换(基于之前的标准),但编译器认为这样的融合并无益处,具体包括以下情况:
  • 两个循环的其中之一由ivdep pragma注释,但不能两个都是。
  • 两个循环其中之一(但不能两者皆是)包含无停顿逻辑。

High-Level Design Report中的Loop Analysis Report显示循环何时被融合。

除了自动循环融合之外, Intel® HLS Compiler还提供两个指令来帮助您控制何时融合循环:
  • nofusion指令

    使用该指令注释循环以请求编译器不融合被批注的循环。

  • loop_fuse指令

    覆盖编译器有益性分析并融合相邻循环以确保其安全。

    使用loop_fuse指令告知编译器考虑融合具有不同行程计数的相邻循环。