标量黄金参考 - 2022.1 简体中文

AI 引擎内核编码 最佳实践指南 (UG1079)

Document ID
UG1079
Release Date
2022-05-25
Version
2022.1 简体中文

AI 引擎包含标量处理器,可用于实现标量数学运算、非线性函数等。有时,代码的黄金标量参考版本很有用。但请注意,通常代码的标量版本在仿真和硬件中运行时所耗费的时间会长得多。

以下提供了 32 抽头滤波器的标量版本的代码示例:
static cint16 eq_coef[32]={{1,2},{3,4},...};

//keep margin data between different executions of graph 
static cint16 delay_line[32];

__attribute__((noinline)) void fir_32tap_scalar(input_stream<cint16> * sig_in,
      output_stream<cint16> * sig_out){
  //For profiling only 
  unsigned cycle_num[2];
  aie::tile tile=aie::tile::current();
  cycle_num[0]=tile.cycles();//cycle counter of the AI Engine tile

  for(int i=0;i<SAMPLES;i++){
    cint64 sum={0,0};//larger data to mimic accumulator
    for(int j=0;j<32;j++){
      //auto integer promotion to prevent overflow
      sum.real+=delay_line[j].real*eq_coef[j].real-delay_line[j].imag*eq_coef[j].imag;
      sum.imag+=delay_line[j].real*eq_coef[j].imag+delay_line[j].imag*eq_coef[j].real;
    }
    sum=sum>>SHIFT;
    //produce one sample per loop iteration
    writeincr(sig_out,{(int16)sum.real,(int16)sum.imag});

    for(int j=0;j<32;j++){
      if(j==31){
        delay_line[j]=readincr(sig_in);
      }else{
        delay_line[j]=delay_line[j+1];
      }
    }
  }
  
  //For profiling only 
  cycle_num[1]=tile.cycles();//cycle counter of the AI Engine tile
  printf("start=%d,end=%d,total=%d\n",cycle_num[0],cycle_num[1],cycle_num[1]-cycle_num[0]);
}
void fir_32tap_scalar_init()
{
  //initialize data
  for (int i=0;i<32;i++){
    int tmp=get_ss(0);
    delay_line[i]=*(cint16*)&tmp;
  }
};
注释:
  • fir_32tap_scalar_init 函数用作为内核的初始化函数,执行 graph.run() 后仅调用一次。
  • 在标量处理器中不支持舍入和饱和模式。这些模式可通过标准 C 语言操作(如,shift)来实现。
  • 拼块计数器用于对代码主循环进行剖析。

从剖析结果中可以看到,每个样本耗时约 3050 个周期。

如需了解有关 graph 构造和不同类型的剖析技巧的信息,请参阅 Versal ACAP AI 引擎编程环境用户指南 (UG1076) 中的基于 AI 引擎仿真的性能分析在硬件上对 AI 引擎 graph 应用进行性能分析