含嵌套循环的编码是很常见的。了解嵌套循环结构中循环的流水打拍方式是实现目标性能的关键。
如果将 HLS PIPELINE 编译指示应用于某个循环,并且此循环嵌套在另一个循环内,那么 v++
编译器会尝试平铺此循环,以创建单一循环,并将 PIPELINE 编译指示应用于所构建的循环。平铺循环有助于改善内核性能。
编译器能够平铺以下类型的嵌套循环:
- 完美嵌套循环:
- 仅限内层循环才有循环主体。
- 循环声明之间不指定任何逻辑或运算。
- 所有循环边界均为常量。
- 半完美嵌套循环:
- 仅限内层循环才有循环主体。
- 循环声明之间不指定任何逻辑或运算。
- 内层循环边界必须为常量,但外层循环边界可为变量。
以下代码示例演示了完美嵌套循环的结构:
ROW_LOOP: for(int i=0; i< MAX_HEIGHT; i++) {
COL_LOOP: For(int j=0; j< MAX_WIDTH; j++) {
#pragma HLS PIPELINE
// Main computation per pixel
}
}
以上示例显示的嵌套循环结构包含两个循环,这两个循环对传入的像素数据执行部分计算。在大部分情况下,您希望在每个周期内对任一像素进行处理,因此将 PIPELINE 应用于嵌套循环主体结构。编译器能够平铺该示例中的嵌套循环结构,因为它是完美嵌套循环。
前述示例中的嵌套循环的两个循环声明之间不包含任何逻辑。在 ROW_LOOP
与 COL_LOOP
未布局任何逻辑;全部处理逻辑都位于 COL_LOOP
内。并且,这两个循环具有固定数量的迭代。这两项条件有助于 v++
编译器平铺循环并应用 PIPELINE 约束。
建议: 如果外层循环具有变量边界,那么编译器仍可平铺此循环。您应始终尝试为内层循环设置常量边界。