Vitis HLS:内联函数外部Array Partition pragma失效致II违例求助
内联函数数组分区与循环展开问题解决
问题背景
要展开内联函数find_match中的find_col循环,因此在mp_buffer和mc_buffer数组的外部声明处设置了维度3、cyclic类型、并行因子为8的#pragma HLS ARRAY_PARTITION指令,再将这两个数组作为参数传入find_match函数。但出现II违例,提示数组未被分区;若在find_match函数内设置该指令,C综合耗时又过长,急需解决。
相关代码
find_match函数代码
inline void find_match ( Feature_Point origin, int origin_u_bin, int origin_v_bin, int origin_col_idx, Feature_Point m_buffer[7][4][COL_BIN_FEATURE_MAX], int32_t m_buffer_num[7][4][V_BIN_NUM+1], Matching_cand m_matching[U_BIN_NUM][4][COL_BIN_FEATURE_MAX] ) { Matching_cand min_cand; int16_t min_cost = 32766; int16_t psum; int16_t psum_03, psum_47, psum_811, psum_1215, psum_1619, psum_2023, psum_2427, psum_2831; int16_t psum_015, psum_1631; int32_t u_min,u_max,v_min,v_max; u_min = origin.u-SEARCH_RAD_U; u_max = origin.u+SEARCH_RAD_U; v_min = origin.v-SEARCH_RAD_V; v_max = origin.v+SEARCH_RAD_V; // bins of interest int32_t u_bin_min = max(origin_u_bin-3, 0); int32_t u_bin_max = min(origin_u_bin+3, U_BIN_NUM-1); int32_t v_bin_min = max(origin_v_bin-3, 0); int32_t v_bin_max = min(origin_v_bin+3, V_BIN_NUM-1); int32_t bin_class = origin.type; int16_t tmp[32]; #pragma HLS ARRAY_PARTITION variable=tmp dim=1 complete // for all bins of interest do find_u_bin: for (int u_bin = u_bin_min; u_bin < u_bin_max; u_bin++) { int u_bin_buffer = u_bin % 7; find_col: for (int col_idx = m_buffer_num[u_bin_buffer][bin_class][v_bin_min]; col_idx < m_buffer_num[u_bin_buffer][bin_class][v_bin_max]; col_idx++) { #pragma HLS UNROLL factor=parallel Feature_Point target = m_buffer[u_bin_buffer][bin_class][col_idx]; if (target.u>=u_min && target.u<=u_max && target.v>=v_min && target.v<=v_max) { psum = 0; calc: for (int i = 0; i < 32; i++) { #pragma HLS UNROLL factor=32 ap_uint<8> a = origin.d.range((i+1)*8-1, 8*i); ap_uint<8> b = target.d.range((i+1)*8-1, 8*i); tmp[i] = ABS(a, b); } // adder tree ... }
外部pragma设置代码
Matching_cand mc_matching[U_BIN_NUM][4][COL_BIN_FEATURE_MAX]; Matching_cand mp_matching[U_BIN_NUM][4][COL_BIN_FEATURE_MAX]; static int _p_matched_num; #pragma HLS ARRAY_PARTITION variable=mc_buffer dim=3 type=cyclic factor=parallel #pragma HLS ARRAY_PARTITION variable=mp_buffer dim=3 type=cyclic factor=parallel find_match(origin, i, v_buffer_idx, col_idx, mp_buffer, mp_buffer_num, mc_matching);
解决方案
1. 显式传递分区属性到内联函数参数
HLS有时无法自动将外部数组的分区属性传递给内联函数的参数,需要在函数内部显式为参数添加一致的分区指令,同时强制函数内联:
__attribute__((always_inline)) inline void find_match ( Feature_Point origin, int origin_u_bin, int origin_v_bin, int origin_col_idx, Feature_Point m_buffer[7][4][COL_BIN_FEATURE_MAX], int32_t m_buffer_num[7][4][V_BIN_NUM+1], Matching_cand m_matching[U_BIN_NUM][4][COL_BIN_FEATURE_MAX] ) { #pragma HLS ARRAY_PARTITION variable=m_buffer dim=3 type=cyclic factor=8 // 原有函数逻辑 }
注意:分区参数要和外部设置完全一致,避免冲突。
2. 优化循环边界的可预测性
find_col循环的上下界依赖运行时变量,HLS难以充分展开循环并利用分区属性,可做以下调整:
- 将循环边界值缓存到本地变量,添加依赖消除指令:
int32_t col_start = m_buffer_num[u_bin_buffer][bin_class][v_bin_min]; int32_t col_end = m_buffer_num[u_bin_buffer][bin_class][v_bin_max]; #pragma HLS DEPENDENCE variable=col_start inter false #pragma HLS DEPENDENCE variable=col_end inter false find_col: for (int col_idx = col_start; col_idx < col_end; col_idx++) { // 循环逻辑 } - 对
m_buffer_num的相关维度也做分区,减少访问延迟:#pragma HLS ARRAY_PARTITION variable=m_buffer_num dim=3 type=cyclic factor=8
3. 调整综合优化策略
- 降低非关键循环的展开因子:如果
find_u_bin循环不需要高并行度,可以去掉其展开指令,减少综合压力 - 调整HLS综合级别:在项目配置中设置
CONFIG OPTIMIZATION_LEVEL=2(不同工具版本可能有差异),平衡综合速度与性能
4. 验证数组访问模式
确保find_col循环展开后,对m_buffer的第三维访问符合cyclic分区的并行规则——即并行访问的索引间隔为8的倍数,避免跨分区访问导致的冲突,确保HLS能有效利用分区后的数组带宽。
内容的提问来源于stack exchange,提问作者TylerChang
相关产品推荐
相关产品推荐

