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

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

6.9.1. 循环融合控制(loop_fuse预处理指令)

使用loop_fuse指令告知编译器尝试融合两个相邻的循环而不影响任一循环的功能,同时覆盖编译器对融合循环的有益性分析。

融合相邻循环有助于减少组件中的循环控制开销量,从而有助于减少所使用的FPGA面积,并且可以通过将两个循环作为一个(融合)循环来执行从而提高性能。

loop_fuse指令应用到一个代码的模块以指示应考虑将代码块中的循环进行融合,如下所示:
#pragma loop_fuse [depth(N)] [independent]
  {
  ...
  }
默认情况下,仅考虑融合相邻的顶层(非嵌套)循环。使用指令的depth(N)子句来指示融合相邻循环时编译器应考虑嵌套深度的级数。指定depth(1)相当于表明只会考虑将相邻的顶层循环进行融合。
#pragma loop_fuse
 // can also be 
// #pragma loop_fuse depth(1)
{
  L1: for(...) {}
  L2: for(...) {
    L3: for(...) {}
    L4: for(...) {
      L5: for(...) {}
      L6: for(...) {}
    }
  } 
}

默认情况下(或depth(1)),最初仅考虑将循环L1和L2进行融合。

#pragma loop_fuse depth(2)
{
  L1: for(...) {}
  L2: for(...) {
    L3: for(...) {}
    L4: for(...) {
      L5: for(...) {}
      L6: for(...) {}
    }
  }
}
以及depth(2),首先考虑以下循环对进行融合:
  • L1和L2
  • L3和L4
#pragma loop_fuse depth(3)
{
  L1: for(...) {}
  L2: for(...) {
    L3: for(...) {}
    L4: for(...) {
      L5: for(...) {}
      L6: for(...) {}
    }
  }
}
对于depth(3),首先考虑以下循环对进行融合:
  • L1和L2
  • L3和L4
  • L5和L6

当循环满足条件时,编译器会自动考虑合并具有相同行程计数的相邻循环。您还可以使用loop_fuse指令告知编译器考虑融合具有不同行程计数的相邻循环。

由于将loop_fuse指令应用于代码块,编译器在确定可以安全合并循环时始终尝试合并块中的相邻循环(具有相同或不同行程计数)。如果两个循环满足循环融合(Loop Fusion)Fusion Criteria部分中描述的合并标准,则认为它们可以安全合并。

如下实例展示了融合具有不同行程计数的循环的效果:
未融合的循环 融合环
#pragma loop_fuse
{
	for (int i = 0; i < N; i++) {
  		// Loop Body 1
	}
	for (int j = 0; j < M; j++) {
  		// Loop Body 2
	}
}
for (int f = 0; f < max(M,N); f++) {
  if (f < N) {
    // Loop Body 1
  }
  if (f < M) {
    // Loop Body 2
  }
}
融合的循环本身可以考虑与其它循环融合。例如,在下面的代码中,首先考虑将L1和L2融合。然后可以考虑将得到的融合循环与L4融合。
#pragma loop_fuse
{
  L1 for(...) {}
  L2 for(...) {
    L3 for(...) {}
  }
  L4 for(...) {}
}

使用independent选项来覆盖依赖项安全检查。如果您指定了independent选项,则表示您向编译器保证由loop_fuse指令指示的循环融合对是安全。换言之,融合循环中没有负距离依赖关系。如果它不安全,您的组件中可能会遇到功能错误。

loop_fuse代码块中的功能调用

如果功能调用发生在带有以loop_fuse指令批注的代码块中 并且并且内联的功能调用包含循环,则生成的循环可以作为循环融合的选择对象。

嵌套式depth(N)子句

当您嵌套loop_fuse指令时,可能会创建重叠的可选对象循环集。

请考虑如下实例:
#pragma loop_fuse depth(2) independent
{
  L1: for(...) {}
  L2: for(...) {
    #pragma loop_fuse depth(2)
    {
      L3: for(...) {}
      L4: for(...) {
        L5: for(...) {}
        L6: for(...) {}
      }
    }
  }
}
在此实例中,编译器考虑融合以下循环对:L1/L2、L3/L4和L5/L6。此外,编译器会覆盖以下循环对的编译器负距离依赖性分析:L1/L2、L3/L4。
另一个实例显示使用loop_fuse指令的效果,请参考以下教程:
<quartus_installdir>/hls/examples/tutorials/best_practices/loop_fusion