アキュムレータ レジスタ - 2023.2 日本語

AI エンジン カーネルおよびグラフ プログラミング ガイド (UG1079)

Document ID
UG1079
Release Date
2023-12-04
Version
2023.2 日本語

アキュムレータ レジスタは 384 ビット幅で、48 ビットのベクター レーンが 8 個含まれます。これにより、32 ビットの乗算結果をビット オーバーフローなしに累算できるようになります。16 ビットのガード ビットにより、最大 216 回の累算が可能です。固定小数点ベクター MAC および MUL 組み込み関数の出力は、アキュムレータ レジスタに格納されます。次の表に、アキュムレータ レジスタのセットと、小さなレジスタを組み合わせて大きなレジスタを形成する方法を示します。

表 1. アキュムレータ レジスタ
384 ビット 768 ビット
aml0 bm0
amh0
aml1 bm1
amh1
aml2 bm2
amh2
aml3 bm3
amh3

アキュムレータ レジスタには、名前の先頭に am が付きます。これらのレジスタを 2 つ組み合わせて、名前の先頭に bm が付いた 768 ビット レジスタが形成されます。

シフト/丸め/飽和を実行する srs() 組み込み関数を使用すると、アキュムレータ レジスタから必要なシフトおよび丸め機能を備えたベクター レジスタに値を移動できます。

aie::vector<int32,8> res = srs(acc, 8); // shift right 8 bits, from accumulator register to vector register

アップシフトを実行する ups() 組み込み関数を使用すると、ベクター レジスタからアキュムレータ レジスタに値を移動できます。

aie::accum<acc48,8> acc = ups(v, 8); //shift left 8 bits, from vector register to accumulator register

set_rnd() および set_sat() 組み込み関数は、累積結果の丸めおよび飽和モードを設定します。clr_rnd() および clr_sat() 組み込み関数は、丸めおよび飽和モードをクリアし、累算結果を切り捨てます。

演算がシフト/丸め/飽和データパスを通過する場合にのみ、シフト、丸め、または飽和モードが有効になります。組み込み関数の中にはベクターの前置加算器演算のみが使用され、シフト、丸め、または飽和モードがコンフィギュレーションに使用されないものもあります。このような演算には、加算、減算、絶対値、ベクター比較、またはベクター選択/シャッフルがあります。シフト、丸め、または飽和モードのコンフィギュレーションを使用した減算の代わりに、MAC 組み込み関数を選択できます。次のコードは、sub 組み込み関数の代わりに、mul を使用して vavb 間で減算を実行します。

v16cint16 va, vb;
int32 zbuff[8]={1,1,1,1,1,1,1,1};
aie::vector<int32,8> coeff=*(v8int32*)zbuff;
aie::accum<acc48,8> acc = mul8_antisym(va, 0, 0x76543210, vb, 0, false, coeff, 0 , 0x76543210);
aie::vector<int32,8> res = srs(acc,0);

浮動小数点組み込み関数には、個別のアキュムレータ レジスタはないので、結果はベクター レジスタに返されます。カスケード ストリームに対して浮動小数点アキュムレータ データの読み出しおよび書き込みを実行するには、次のストリーミング データ API を使用できます。

aie::vector<float,8> readincr_v<8>(input_cascade<accfloat> * str);
aie::vector<cfloat,4> readincr_v4(input_cascade<caccfloat> * str);
void writeincr_v8(output_cascade<accfloat>* str, v8float value);
void writeincr_v4(output_cascade<caccfloat>* str, v4cfloat value);

ウィンドウおよびストリーミング データ API の詳細は、入力および出力バッファー を参照してください。

メモリのデータ サイズは、次の 2 のべき乗 (acc48 では 64b) に揃えられるので、sizeof を使用して要素の位置を取得するのがベストです。次に、アキュムレータ ベクター レジスタを表示するコード例を示します。

aie::accum<acc48,8> vacc; //cascade value
const int SIZE_ACC48=sizeof(aie::accum<acc48,8>)/8;
for(int i=0;i<8;i++){//8 number
  int8 *p=(int8*)&vacc+SIZE_ACC48*i;//point to start of each acc48
  printf("acc value[%d]=0x",i);
  for(int j=5;j>=0;j--){//print each acc48 from higher byte to lower byte
    printf("%02x",*(p+j));
  }
  printf("\n");
}

出力は次のようになります。

acc value[0]=0x000000000000
acc value[1]=0x000000000001
acc value[2]=0x000000000002
acc value[3]=0x000000000003
acc value[4]=0x000000000004
acc value[5]=0x000000000005
acc value[6]=0x000000000006
acc value[7]=0x000000000007