并行串流访问 - 2022.1 简体中文

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

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

对于串流输入和输出接口,如果性能受到串流数量限制,AI 引擎能够并行使用两个串流输入或两个串流输出来代替一个串流输入或输出。

要使用两条并行串流,可使用以下宏,其中 idx1idx2 是两条串流。将 __restrict 关键字添加到串流端口可确保对这些串流端口加以最优化以便于并行处理。

int READINCR(SS_rsrc1, input_stream<T> *idx1)
int READINCR(SS_rsrc2, input_stream<T> *idx2)
void WRITEINCR(MS_rsrc1, output_stream<T> *idx1, int val)
void WRITEINCR(MS_rsrc2, output_stream<T> *idx2, int val)
int READINCRT(SS_rsrc1, input_stream<T> *idx1, bool &tlast)
int READINCRT(SS_rsrc2, input_stream<T> *idx2, bool &tlast)
void WRITEINCRT(MS_rsrc1, output_stream<T> *idx1, int val, int tlast)
void WRITEINCRT(MS_rsrc2, output_stream<T> *idx2, int val, int tlast)
或者每 4 个周期内基于 128 位执行运算:
aie::vector<int32,4> READINCRW(WSS_rsrc1, input_stream<T> *idx1)
aie::vector<int32,4> READINCRW(WSS_rsrc2, input_stream<T> *idx2)
void WRITEINCRW(WMS_rsrc1, output_stream<T> *idx1, v4int32 val)
void WRITEINCRW(WMS_rsrc2, output_stream<T> *idx2, v4int32 val)
aie::vector<int32,4> READINCRWT(WSS_rsrc1, input_stream<T> *idx1, bool &tlast)
aie::vector<int32,4> READINCRWT(WSS_rsrc2, input_stream<T> *idx2, bool &tlast)
void WRITEINCRWT(WMS_rsrc1, output_stream<T> *idx1, val, int tlast)
void WRITEINCRWT(WMS_rsrc2, output_stream<T> *idx2, val, int tlast)

以下代码样本演示了如何使用两条并行输入串流来达成间隔为 1 的流水打拍。这表示每个周期内有两次读取、一次写入和一次加法。

void simple(   input_stream_int32 * __restrict data0,  
			input_stream_int32 * __restrict data1,   			
			output_stream_int32 * __restrict out) { 
	for(int i=0; i<1024; i++) 
	chess_prepare_for_pipelining 
	{ 
		int32_t d = READINCR(SS_rsrc1, data0) ; 
		int32_t e = READINCR(SS_rsrc2, data1) ; 
		WRITEINCR(MS_rsrc1,out,d+e); 
	} 
}
以下提供了矢量化版本用于并行读取串流,并达成最佳循环性能:
void vect_mul(input_stream<int8>* __restrict data1, input_stream<int8>* __restrict data2, 
      output_stream<int8>* __restrict out){
  for(int i=0;i<(2<<20-1);i++)
  chess_prepare_for_pipelining
  {
    aie::vector<int32,4> va=READINCRW(WSS_rsrc1, data1);
    aie::vector<int32,4> vb=READINCRW(WSS_rsrc2, data2);
    aie::vector<int8,16> va_int8=va.cast_to<int8>();
    aie::vector<int8,16> vb_int8=vb.cast_to<int8>();
    auto vc=aie::mul(va_int8,vb_int8);
    writeincr(out,vc.to_vector<int8>(0));
  }
}
另一种指引工具使用并行串流的方法是使用 aie_stream_resource_inaie_stream_resource_out 注解搭配不同的枚举值,例如,使用 aie_stream_resource_in::aaie_stream_resource_in::b 作为输入串流。例如:
void vect_mul(input_stream<int8>* __restrict data1, input_stream<int8>* __restrict data2,
      output_stream<int8>* __restrict out){
  while(true)
  chess_prepare_for_pipelining
  chess_loop_range(8,)
  {
    aie::vector<int8,16> va_int8=readincr_v<16,aie_stream_resource_in::a>(data1);
    aie::vector<int8,16> vb_int8=readincr_v<16,aie_stream_resource_in::b>(data2);
    auto vc=aie::mul(va_int8,vb_int8);
    writeincr<aie_stream_resource_out::a>(out,vc.to_vector<int8>(0));

    va_int8=readincr_v<16,aie_stream_resource_in::a>(data1);
    vb_int8=readincr_v<16,aie_stream_resource_in::b>(data2);
    vc=aie::mul(va_int8,vb_int8);
    writeincr(out,vc.to_vector<int8>(0));
  }
}

同样,aie_stream_resource_out::aaie_stream_resource_out::b 可用于表示两条并行输出串流。