You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 07:35:21