Contenu connexe Similaire à PBL1-v1-004j.pptx (20) PBL1-v1-004j.pptx1. CPU GPU
Ultimate CGRA w/ high-speed compiler
CGRA for Energy-efficient Cryptography
Beyond-Neuromorphic Systems
Non-Deterministic Computing
1
ナレータ VOICEVOX:もち子(cv 明日葉よもぎ)
はらぺこエンジニアに贈るCGRAの世界2022
(4. 画像フィルタ上級編)
スパコンからIoTまで 省エネ社会に
AI+BCだけじゃない超効率計算手法
3. 20220202
3
フレーム補間処理1 4x4領域を上下左右8画素移動して類似度を計算
#define ad(a,b) ((a)<(b)?(b)-(a):(a)-(b))
#define df(l,r) (ad((l)>>24&255,(r)>>24&255)
+ad((l)>>16&255,(r)>>16&255)
+ad((l)>> 8&255,(r)>> 8&255))
short SAD1[HT/4][8][WD/4][8];
for (row=8; row<HT-8; row++) { /* scan-lines */
for (ofs=-4; ofs<4; ofs++) {
for (col=0; col<WD; col++) {
int j = col/4*4;
int k = col%4*2;
Uint *new = frame2+row*WD;
Uint *old = frame1+(row+ofs)*WD;
SAD1[row/4][ofs+4][col/4][k ] += df(new[j ],old[j+k-4]) + df(new[j+1],old[j+k-3])
+ df(new[j+2],old[j+k-2]) + df(new[j+3],old[j+k-1]);
SAD1[row/4][ofs+4][col/4][k+1] += df(new[j ],old[j+k-3]) + df(new[j+1],old[j+k-2])
+ df(new[j+2],old[j+k-1]) + df(new[j+3],old[j+k ]);
}
}
}
4. 20220202
4
フレーム補間処理1 4x4領域を上下左右8画素移動して類似度を計算
for (row=0; row<HT; row++) {
//EMAX5A begin hokan1 mapdist=7
for (CHIP=0; CHIP<NCHIP; CHIP++) { /* output channels are parallelized by multi-chip (OC/#chip) */
for (INIT0=1,LOOP0=WD,col=0-4LL; LOOP0--; INIT0=0) {
exe(OP_ADD, &col, col, EXP_H3210, 4, EXP_H3210, 0, EXP_H3210, OP_AND, 0x0ffffffffLL, OP_NOP, 0);
exe(OP_NOP, &jw, col, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_AND, ~15, OP_SLL, 0);
exe(OP_NOP, &kw, col, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_AND, 12, OP_SLL, 1);
exe(OP_ADD, &r12, new, EXP_H3210, jw, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_ADD3, &r13, old, EXP_H3210, jw, EXP_H3210, kw, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r0, r12, 0, MSK_D0, new, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r1, r12, 4, MSK_D0, new, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r2, r12, 8, MSK_D0, new, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r3, r12, 12, MSK_D0, new, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &BR[4][0][1], r13, -16, MSK_D0, old, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r25, r13, -12, MSK_D0, old, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r26, r13, -8, MSK_D0, old, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r27, r13, -4, MSK_D0, old, WD, 0, 0, NULL, 0);
mop(OP_LDWR, &r28, r13, 0, MSK_D0, old, WD, 0, 0, NULL, 0);
exe(OP_MSSAD, &r11, 0, EXP_H3210, r0, EXP_H3210, r25, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r13, 0, EXP_H3210, r1, EXP_H3210, r26, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r15, 0, EXP_H3210, r2, EXP_H3210, r27, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r17, 0, EXP_H3210, r3, EXP_H3210, r28, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r10, 0, EXP_H3210, r0, EXP_H3210, BR[4][0][1], EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r12, 0, EXP_H3210, r1, EXP_H3210, r25, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r14, 0, EXP_H3210, r2, EXP_H3210, r26, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r16, 0, EXP_H3210, r3, EXP_H3210, r27, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH, &r20, r10, EXP_H3210, r12, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH, &r21, r11, EXP_H3210, r13, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH, &r24, r14, EXP_H3210, r16, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH, &r25, r15, EXP_H3210, r17, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH, &r10, r20, EXP_H3210, r24, EXP_H3210, 0, EXP_H3210, OP_SUMHL,0, OP_NOP, 0);
exe(OP_MAUH, &r11, r21, EXP_H3210, r25, EXP_H3210, 0, EXP_H3210, OP_SUMHH,0, OP_NOP, 0);
mop(OP_LDWR, &BR[9][0][1], out, col, MSK_D0, out, WD, 0, 1, NULL, 0);
exe(OP_MAUH3, &AR[9][0], BR[9][0][1], EXP_H3210, r10, EXP_H3210, r11, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_STWR, &AR[9][0], col, out, MSK_D0, out, WD, 0, 1, NULL, 0);
: 次の行の処理が続く(LDの距離が7UNIT分なので、mapdist=7)
}
}
//EMAX5A end
}
5. 20220202
5
フレーム補間処理2 類似度SADの中から最小値を選ぶ
for (row=8; row<HT-8; row+=4) {
Uint *xy = minxy+top*WD;
for (ofs=-4; ofs<4; ofs++) {
idx = ((ofs/2)&0xff)<<16;
for (col=0; col<WD; col++) {
l1 = ((-2)<<24)|idx|SAD1[row/4][ofs+4][col/4][0];
l2 = ((-1)<<24)|idx|SAD1[row/4][ofs+4][col/4][1];
l3 = ((-1)<<24)|idx|SAD1[row/4][ofs+4][col/4][2];
l4 = (( 0)<<24)|idx|SAD1[row/4][ofs+4][col/4][3];
l5 = (( 0)<<24)|idx|SAD1[row/4][ofs+4][col/4][4];
l6 = (( 0)<<24)|idx|SAD1[row/4][ofs+4][col/4][5];
l7 = (( 1)<<24)|idx|SAD1[row/4][ofs+4][col/4][6];
l8 = (( 1)<<24)|idx|SAD1[row/4][ofs+4][col/4][7];
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][0]) xy[row][col] = l1;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][1]) xy[row][col] = l2;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][2]) xy[row][col] = l3;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][3]) xy[row][col] = l4;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][4]) xy[row][col] = l5;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][5]) xy[row][col] = l6;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][6]) xy[row][col] = l7;
if ((xy[row][col]&0xffff) > SAD1[row/4][ofs+4][col/4][7]) xy[row][col] = l8;
}
}
}
6. 20220202
6
フレーム補間処理2 類似度SADの中から最小値を選ぶ
for (row=0; row<HT; row++) {
//EMAX5A begin hokan2 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) { /* output channels are parallelized by multi-chip (OC/#chip) */
for (INIT0=1,LOOP0=WD,col=0-4LL; LOOP0--; INIT0=0) {
exe(OP_ADD, &col, col, EXP_H3210, 4LL, EXP_H3210, 0, EXP_H3210, OP_AND, 0x000ffffffffLL, OP_NOP, 0);
/*k=-4*/
mop(OP_LDWR, &r10, t00, col, MSK_D0, t00, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r28, -2<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix0, OP_NOP, 0);
mop(OP_LDWR, &r12, t01, col, MSK_D0, t00, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r29, -1<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix0, OP_NOP, 0);
mop(OP_LDWR, &r14, t02, col, MSK_D0, t00, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r31, 1<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix0, OP_NOP, 0);
mop(OP_LDWR, &r16, t03, col, MSK_D0, t00, WD, 0, 0, NULL, 0);
exe(OP_MINL3, &r10, r29, EXP_H3210, r28, EXP_H3210, r10, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r12, ix0, EXP_H3210, r29, EXP_H3210, r12, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r14, ix0, EXP_H3210, ix0, EXP_H3210, r14, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r16, r31, EXP_H3210, r31, EXP_H3210, r16, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r20, r10, EXP_H3210, r12, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r24, r14, EXP_H3210, r16, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r0, r20, EXP_H3210, r24, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
/*k=-3*//*k=-2*//*k=-1*//*k=0*//*k=1*//*k=2*//*k=3*/
mop(OP_LDWR, &r10, t70, col, MSK_D0, t70, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r28, -2<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix7, OP_NOP, 0);
mop(OP_LDWR, &r12, t71, col, MSK_D0, t70, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r29, -1<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix7, OP_NOP, 0);
mop(OP_LDWR, &r14, t72, col, MSK_D0, t70, WD, 0, 0, NULL, 0);
exe(OP_NOP, &r31, 1<<24, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, ix7, OP_NOP, 0);
mop(OP_LDWR, &r16, t73, col, MSK_D0, t70, WD, 0, 0, NULL, 0);
exe(OP_MINL3, &r10, r29, EXP_H3210, r28, EXP_H3210, r10, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r12, ix7, EXP_H3210, r29, EXP_H3210, r12, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r14, ix7, EXP_H3210, ix7, EXP_H3210, r14, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL3, &r16, r31, EXP_H3210, r31, EXP_H3210, r16, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r20, r10, EXP_H3210, r12, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r24, r14, EXP_H3210, r16, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r1, r20, EXP_H3210, r24, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MINL, &r0, r1, EXP_H3210, r0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &BR[33][0][1], xy, col, MSK_D0, xy, WD, 0, 1, NULL, 0);
exe(OP_MINL, &AR[33][0], r0, EXP_H3210, BR[33][0][1], EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_STWR, &AR[33][0], col, xy, MSK_D0, xy, WD, 0, 1, NULL, 0);
}
}
//EMAX5A end
}
//EMAX5A drain_dirty_lmm
7. 20220202
7
フレーム補間処理3 位置情報を使って画像を貼り付ける
for (row=8; row<HT-8; row++) {
for (ofs=-2; ofs<2; ofs++) {
for (col=0; col<WD; col++) {
x = (int) xy[row/4*4][col/4*4]>>24;
y = (int)(xy[row/4*4][col/4*4]<<8)>>24;
if (y == ofs) out[row][ofs] = in[row][ofs+x];
}
}
}
8. 20220202
8
フレーム補間処理3 位置情報を使って画像を貼り付ける
for (row=0; row<HT; row++) {
//EMAX5A begin hokan3 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT0=1,LOOP0=WD,col=0-4LL; LOOP0--; INIT0=0) {
exe(OP_ADD, &col, col, EXP_H3210, 4LL, EXP_H3210, 0, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);
exe(OP_NOP, &jw, col, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_AND, ~15LL, OP_SLL, 0);
mop(OP_LDWR, &r10, xy, jw, MSK_D0, xy, WD, 0, 0, NULL, WD);
exe(OP_NOP, &r2, r10, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_AND, 0xff000000LL, OP_SRAA, 22);/* x */
exe(OP_NOP, &r3, r10, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_AND, 0x00ff0000LL, OP_SRAB, 16);/* y */
exe(OP_ADD, &r4, r2, EXP_H3210, col, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r10, in0, r4, MSK_D0, in0, WD, 0, 0, NULL, WD);/*in0行目*/
exe(OP_CMP_EQ, &r5, r3, EXP_H3210, -2, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);/* y==-2? */
exe(OP_CMOV, &r0, r5, EXP_H3210, r10, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r10, in1, r4, MSK_D0, in1, WD, 0, 0, NULL, WD);/*in1行目*/
exe(OP_CMP_EQ, &r5, r3, EXP_H3210, -1, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);/* y==-1? */
exe(OP_CMOV, &r0, r5, EXP_H3210, r10, EXP_H3210, r0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r10, in2, r4, MSK_D0, in2, WD, 0, 0, NULL, WD);/*in2行目*/
exe(OP_CMP_EQ, &r5, r3, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);/* y== 0? */
exe(OP_CMOV, &r0, r5, EXP_H3210, r10, EXP_H3210, r0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r10, in3, r4, MSK_D0, in3, WD, 0, 0, NULL, WD);/*in3行目*/
exe(OP_CMP_EQ, &r5, r3, EXP_H3210, 1, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);/* y== 1? */
exe(OP_CMOV, &r0, r5, EXP_H3210, r10, EXP_H3210, r0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_STWR, &r0, out, col, MSK_D0, out, WD, 0, 1, NULL, WD);
}
}
//EMAX5A end
}
//EMAX5A drain_dirty_lmm
9. 20220202
9
超解像
for (Y=0; Y<768; Y++) {
k = Y*240/768;
kfraq = (((Y*240)<<4)/768)&15;
for (X=0; X<1024; X++) {
l = X*320/1024;
lfraq = (((X*320)<<4)/1024)&15;/
out[Y][X] = ((in[k ][l ]>>24&0xff)*r1 + (in[k ][l-1]>>24&0xff)*r2 + (in[k ][l+1]>>24&0xff)*r3
+ (in[k-1][l ]>>24&0xff)*r4 + (in[k+1][l ]>>24&0xff)*r5 + (in[k-1][l-1]>>24&0xff)*r6
+ (in[k-1][l+1]>>24&0xff)*r7 + (in[k+1][l-1]>>24&0xff)*r8 + (in[k+1][l+1]>>24&0xff)*r9)/256<<24
| ((in[k ][l ]>>16&0xff)*r1 + (in[k ][l-1]>>16&0xff)*r2 + (in[k ][l+1]>>16&0xff)*r3
+ (in[k-1][l ]>>16&0xff)*r4 + (in[k+1][l ]>>16&0xff)*r5 + (in[k-1][l-1]>>16&0xff)*r6
+ (in[k-1][l+1]>>16&0xff)*r7 + (in[k+1][l-1]>>16&0xff)*r8 + (in[k+1][l+1]>>16&0xff)*r9)/256<<16
| ((in[k ][l ]>> 8&0xff)*r1 + (in[k ][l-1]>> 8&0xff)*r2 + (in[k ][l+1]>> 8&0xff)*r3
+ (in[k-1][l ]>> 8&0xff)*r4 + (in[k+1][l ]>> 8&0xff)*r5 + (in[k-1][l-1]>> 8&0xff)*r6
+ (in[k-1][l+1]>> 8&0xff)*r7 + (in[k+1][l-1]>> 8&0xff)*r8 + (in[k+1][l+1]>> 8&0xff)*r9)/256<<8;
}
}
K-1
K = Y*240/768
L-1 L = X*320/1024
(X,Y) 1024x768の1画素
(L,K) 320x240画像
kfraq = (((Y*240)<<4)/ 768)&15;/* 4bit */
lfraq = (((X*320)<<4)/1024)&15;/* 4bit */
Y=1 kfraq= 5/16
Y=2 kfraq=10/16
Y=3 kfraq=15/16
Y=4 kfraq= 4/16
Y=5 kfraq= 9/16
X=1 lfraq= 5/16
X=2 lfraq=10/16
X=3 lfraq=15/16
X=4 lfraq= 4/16
X=5 lfraq= 9/16
10. 20220202
10
超解像
for (Y=0; Y<768; Y++) {
//EMAX5A begin expand4k mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT0=1,LOOP0=1024; LOOP0--; INIT0=0) {
exe(OP_MSUH, &r1, r4, EXP_H3210, 8, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSUH, &r2, 8, EXP_H3210, r4, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r3, 0, EXP_H3210, r4, EXP_H3210, 8, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSUH, &r3, 16, EXP_H3210, r3, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r21, sk2, EXP_H3210, r1, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r10, r0, -1276, MSK_D0, in, 320, 0, 0, NULL, 0);
exe(OP_MLUH, &r22, sk2, EXP_H3210, r2, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r11, r0, -1284, MSK_D0, in, 320, 0, 0, NULL, 0);
exe(OP_MLUH, &r23, sk2, EXP_H3210, r3, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r12, r0, -1280, MSK_D0, in, 320, 0, 0, NULL, 0);
exe(OP_MLUH, &r13, r10, EXP_B5410, r21, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r14, r11, EXP_B5410, r22, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r15, r12, EXP_B5410, r23, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH3, &r16, r13, EXP_H3210, r14, EXP_H3210, r15, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r13, r10, EXP_B7632, r21, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r14, r11, EXP_B7632, r22, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MLUH, &r15, r12, EXP_B7632, r23, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH3, &r17, r13, EXP_H3210, r14, EXP_H3210, r15, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
:
exe(OP_MAUH3, &r21, r13, EXP_H3210, r14, EXP_H3210, r15, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH3, &r21, r17, EXP_H3210, r19, EXP_H3210, r21, EXP_H3210, OP_OR, 0, OP_SRLM, 8);
exe(OP_MAUH3, &r20, r16, EXP_H3210, r18, EXP_H3210, r20, EXP_H3210, OP_OR, 0, OP_SRLM, 8);
exe(OP_MH2BW, &r31, r21, EXP_H3210, r20, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_STWR, &r31, out++, 0, MSK_D0, out, 1024, 0, 0, NULL, 1024);
}
}
//EMAX5A end
}
12. for (row=-8; row<240-8; row++) {
//EMAX5A begin wdifline mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT0=1,LOOP0=320,col=0-4LL; LOOP0--; INIT0=0) {
exe(OP_ADD, &col, col, EXP_H3210, 4LL, EXP_H3210, 0, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);
exe(OP_ADD, &rofs1, L, EXP_H3210, col, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_ADD, &rofs2, R, EXP_H3210, col, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r2, rofs1, 0, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r3, rofs1, 4, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r4, rofs1, 8, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r5, rofs1, 12, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r6, rofs2, 0, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r7, rofs2, 4, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r8, rofs2, 8, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r9, rofs2, 12, MSK_D0, R, 320, 0, 0, NULL, 320);
exe(OP_MSAD, &r22, r2, EXP_H3210, r6, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r12, rofs1, 16, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r13, rofs1, 20, MSK_D0, L, 320, 0, 0, NULL, 320);
exe(OP_MSAD, &r23, r3, EXP_H3210, r7, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r14, rofs1, 24, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r15, rofs1, 28, MSK_D0, L, 320, 0, 0, NULL, 320);
exe(OP_MSAD, &r24, r4, EXP_H3210, r8, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r16, rofs2, 16, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r17, rofs2, 20, MSK_D0, R, 320, 0, 0, NULL, 320);
exe(OP_MSAD, &r25, r5, EXP_H3210, r9, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r18, rofs2, 24, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r19, rofs2, 28, MSK_D0, R, 320, 0, 0, NULL, 320);
exe(OP_MSSAD, &r12, r22, EXP_H3210, r12, EXP_H3210, r16, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r2, rofs1, 32, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r3, rofs1, 36, MSK_D0, L, 320, 0, 0, NULL, 320);
exe(OP_MSSAD, &r13, r23, EXP_H3210, r13, EXP_H3210, r17, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r4, rofs1, 40, MSK_D0, L, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r5, rofs1, 44, MSK_D0, L, 320, 0, 0, NULL, 320);
exe(OP_MSSAD, &r14, r24, EXP_H3210, r14, EXP_H3210, r18, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r6, rofs2, 32, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r7, rofs2, 36, MSK_D0, R, 320, 0, 0, NULL, 320);
exe(OP_MSSAD, &r15, r25, EXP_H3210, r15, EXP_H3210, r19, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_LDWR, &r8, rofs2, 40, MSK_D0, R, 320, 0, 0, NULL, 320);
mop(OP_LDWR, &r9, rofs2, 44, MSK_D0, R, 320, 0, 0, NULL, 320);
exe(OP_MSSAD, &r22, r12, EXP_H3210, r2, EXP_H3210, r6, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r23, r13, EXP_H3210, r3, EXP_H3210, r7, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r24, r14, EXP_H3210, r4, EXP_H3210, r8, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MSSAD, &r25, r15, EXP_H3210, r5, EXP_H3210, r9, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH3, &r31, r22, EXP_H3210, r23, EXP_H3210, r24, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
exe(OP_MAUH3, &r1, r31, EXP_H3210, r25, EXP_H3210, 0, EXP_H3210, OP_SUMHL,0, OP_NOP, 0);
mop(OP_LDWR, &BR[8][0][1], sad2, col, MSK_D0, sad2, 320, 0, 1, NULL, 320);
exe(OP_ADD, &AR[8][0], BR[8][0][1], EXP_H3210, r1, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);
mop(OP_STWR, &AR[8][0], col, sad2, MSK_D0, sad2, 320, 0, 1, NULL, 320);
:のこり15か所のSADにも加算
}
}
//EMAX5A end
}
//EMAX5A drain_dirty_lmm
20220202
12
ステレオマッチング
Notes de l'éditeur 様々なアプリケーションを取りあげて、アイマックスのポテンシャルを説明するシリーズです。第4回は、フレーム補間、超解像、ステレオマッチングです。 フレーム補間は、左上の画像と左下の画像を比較し、真ん中の画像のように、移動領域と方向を検出し、移動量を半分にして、右端の補間画像を生成する画像処理です。毎秒60フレームの動画を、毎秒120フレームに増やして、動きを滑らかにすることができます。なお、一度に生成することは難しいので、3つの処理に分解して、段階的に計算を進めていきます。ちなみに、真ん中の画像は途中の計算結果です。右方向への移動を検出した領域は、赤、した方向は緑、右下方向は黄色です。赤丸部分に注目すると、左下の画像では、灯篭の一部が右にずれています。補間画像では、ずれが半分になっています。 まず、最初の処理では、4かける4領域ごとに、片方の画像を、上下に8画素、左右に8画素ずらしながら、他方の画像と比較して、類似度を配列、SAD1に格納します。ということは、2つの画像に、上下左右8画素以上の移動があったら、計算は困難ということです。これは、元のC言語です。最内ループでは、右に4画素ずらしては、8通りのずれに対して、2つの類似度を一度に計算しています。なお、類似度の計算には、差分絶対ち総和、SADを使います。RGBの要素ごとに引き算をして、絶対ちを求め、4かける4領域ごとの総和を求めます。SADが小さいほど、画像が似ていることを意味します。SADは16ビットなので、32ビットレジスタに2つ入っています。 アイマックスに書き換えると、こうなります。8行分の比較を一度に行うために、ここに見えているコードの下に、同じようなコードが7組隠れています。そして、ここに見えているロード関数と、次の組のロード関数が7ユニット分離れているので、ローカルメモリを再利用するために必要なマップディストは7になります。うえの赤いぎょうは、jとkの計算です。論理積演算とシフト演算を組み合わせて、一度にインデックスを計算し、ベースアドレスを足して、続く8個のロード関数に渡しています。最後の赤丸部分に、今までなかったパラメータが見えます。領域先頭アドレスとワード数の次に、0、1とありますね。0は、今は使っていません。1は、前回のローカルメモリのアドレス領域と同じであっても、内容が更新されることを伝えています。よく見ると、赤丸部分のロードとストアが同じローカルメモリに写像され、ロードしたあたいに、SADの計算結果を足して、同じアドレスに書き戻しています。この場合、計算結果を追い出して、機能の写像位置がずれた後に、アドレスが同じであっても、改めて、主記憶からローカルメモリにデータを持ってくる必要があります。この情報を元に、アイマックスコンパイラは、DMAを制御します。もし、マップディストが0であれば、同じローカルメモリを次々更新するだけなので、途中のDMAを省略したコードが生成されます。 次に、処理2では、4かける4領域ごとに記録された、8かける8のSADのなかから、SADが最小になる、XY方向のずれ情報を選択します。C言語で書いた、このプログラムでは、条件文をたくさん使っています。一般的に、条件文がたくさんあると、簡単な非ノイマン型ハードウェアでは実行できなくなります。 では、アイマックスのコードを見てみましょう。赤字のロード関数ひとつは、前に計算した16ビットのSADが、2つ入った、32ビットデータをロードしています。そして、MINL3は、ロードしたSADの上16ビットと、下16ビットを比較して、上が小さければ1番目のデータ、下が小さければ2番目のデータと、SADを32ビットデータに合体させます。4つのロード関数で、横方向の8個のSADを持ってきて、以上を繰り返すと、横方向のSAD最小値を見つけることができます。さらに、この処理の組を、縦に8組並べることで、8かける8のSADの中から最小値を探し出すことができます。該当する位置情報、つまり、なん画素ずらせば、中間画像になるかの位置補正情報を、最後の青字のロードストアを使って、配列xyにストアします。 位置補正情報が生成出来たら、最後に、元の4かける4画像を補正通りにずらしながら、結果画像を作っていきます。これは簡単です。 アイマックスのコードも、こんなに簡単です。縦方向に、4か所の候補画素を取って来ておくので、青字のロード関数を4回使っています。そして、比較機能CMPEQと、条件付き代入機能CMOVを使って、縦の補正位置が一致した画素だけを採用し、最後の赤字のストア関数で画素を書き込んでいます。このように、アイマックスでは、簡単な条件文であれば、そのまま写像することができます。 次は、超解像です。これは、320かける240の画像を、1024かける768に変換するといった、画像処理です。単に大きくすると、ギザギザになってしまいますが、超解像は、あたかも情報量が増えたかのように、周囲の画素を混ぜて、なめらかに拡大します。実際には情報量は増えていませんけどね。考え方は単純です。変換先解像度の1画素ごとに、元画像のどの位置に対応するかを計算します。その点を含む2かける2の領域を対象に、かさなる部分の面積に応じて、4つの画素値に重みをかけ、合計するだけです。浮動小数点演算を使うと大がかりになるので、かさなる部分は、画素の1辺の16ぶんの1刻みで、粗く計算します。面積計算は省略していますが、概ね、このような形のプログラムになります。 アイマックスのコードです。途中を省略しているので、ロード関数が3つしかありませんが、実際には、前のページの通り、9個のロードがあり、16ユニットで最後のストアまではいります。つまり、64ユニットには36個のロードと4個のストアを収容可能です。1クロックで結果が出る11ビット乗算、MLUHのおかげで、コンパクトな実装ができます。 最後は、ステレオマッチングです。ステレオマッチングは、左右のカメラ画像から、奥行き情報を計算します。何かが接近してきたら、自動的にブレーキを踏むといった使い道があります。カーネル部分のみを取り出すと、フレーム補間にとても良く似ています。違いは、周辺の4かける4領域の比較ではなく、水平方向の広い範囲で、16かける16領域を比較する点にあります。右の図のひだりはしは、無限えんてんを見ている状態、つまり、視差ゼロの状態です。全ての座標について、周辺の16かける16領域のSADを計算し、記録します。そして、視差を増やしながら、類似度を計算し、以前のSADよりも小さい座標は、SADと視差の記録の両方を更新します。これを繰り返すと、遠くにある物体から、手前にある物体まで、順に検出できます。下のプログラムは、SAD計算の部分です。本物は、このあと、輪郭情報と組み合わせて精度を上げます。 アイマックスのコードです。赤字は左目画像のロード、緑は右目画像のロードです。青字は、これまでと同じ、同一ローカルメモリに対するロード、加算、ストアです。画像全体では、1行ずつ下にずれていくので、この、1行分のSAD結果は、他の15か所の加算にも使います。ここでは省略していますが、さらに下に、青字の3行が、15回出てきます。これでも、64ユニットのうち、まだ24ユニットしか使っていません。ところで、16かける16領域といったのに、横方向のロードの数が12個しかありません。これは、単に、12に減らしても、結果にあまり影響がないことがわかったからです。64ユニットに入らないから減らしたわけではありません。 今回は、少し複雑な画像処理を題材に、ローカルメモリへの強制データ転送機能、SAD演算機能、条件付き代入、同一ローカルメモリに対する、ロード、更新演算、ストアなど、アイマックスのデータフロー制御機能を説明しました。ユニット数が64というと、なんだか大したことないように聞こえますが、ユニットは高機能で、1つに40命令相当、64ユニットでは2560命令相当を写像することができます。CPUの世界では、命令を簡素化したリスクが主流ですが、CGRAでは、演算機能を簡素化すると、演算の組み合わせが増え、コンパイラの探索が爆発的に増えます。また、演算をつなぐために、たくさんの長距離配線を使うことになります。CGRAでは、経験的に、局所的に高機能を詰め込む、シスクベースの設計が向いていると思います。ということで、アイマックスは、そういう作りになっています。プログラムが、一見、大変そうに見えるのは、そのためです。省エネコンピュータと、誰でも簡単にプログラムできるコンピュータは、両立できないと考えると、このトレードオフを理解できることでしょう。では、今回はここまでです。おつかれさま。