Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

# PBL1-v1-009j.pptx

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Prochain SlideShare
PBL1-v1-006j.pptx
Chargement dans…3
×

## Consultez-les par la suite

1 sur 12 Publicité

# PBL1-v1-009j.pptx

IMAX3: Amazing Dataflow-Centric CGRA and its Applications
I present this slide to all hungry engineers who are tired of CPU, GPU, FPGA, tensor core, AI core, who want some challenging one with no black box inside, and who want to improve by themselves.

IMAX3: Amazing Dataflow-Centric CGRA and its Applications
I present this slide to all hungry engineers who are tired of CPU, GPU, FPGA, tensor core, AI core, who want some challenging one with no black box inside, and who want to improve by themselves.

Publicité
Publicité

## Plus De Contenu Connexe

Publicité

### PBL1-v1-009j.pptx

1. 1. CPU GPU Ultimate CGRA w/ high-speed compiler CGRA for Energy-efficient Cryptography Beyond-Neuromorphic Systems Non-Deterministic Computing 1 ナレータ VOICEVOX:もち子(cv 明日葉よもぎ) はらぺこエンジニアに贈るCGRAの世界2022 （9. ハッシュ計算とFFTと文字列検索編） スパコンからIoTまで 省エネ社会に AI+BCだけじゃない超効率計算手法
2. 2. 20220202 2 ハッシュ計算には、面倒な演算が必要 for (i=0; i<ctx->mbuflen; i+=BLKSIZE) { /* 1データ流内の並列実行は不可能. 多数データ流のパイプライン実行のみ */ for (th=0; th<thnum; th++) { sregs[th*8+0] = state[th*8+0]; sregs[th*8+1] = state[th*8+1]; sregs[th*8+2] = state[th*8+2]; sregs[th*8+3] = state[th*8+3]; sregs[th*8+4] = state[th*8+4]; sregs[th*8+5] = state[th*8+5]; sregs[th*8+6] = state[th*8+6]; sregs[th*8+7] = state[th*8+7]; } for (j=0; j<BLKSIZE; j+=BLKSIZE/DIV) { for (th=0; th<thnum; th++) { a = sregs[th*8+0]; b = sregs[th*8+1]; c = sregs[th*8+2]; d = sregs[th*8+3]; e = sregs[th*8+4]; f = sregs[th*8+5]; g = sregs[th*8+6]; h = sregs[th*8+7]; #if (DIV==4) t1 = h+EP1(e)+CH(e,f,g)+k[j+ 0]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 0]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 1]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 1]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 2]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 2]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 3]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 3]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 4]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 4]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 5]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 5]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 6]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 6]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 7]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 7]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 8]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 8]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+ 9]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+ 9]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+10]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+10]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+11]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+11]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+12]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+12]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+13]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+13]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+14]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+14]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; t1 = h+EP1(e)+CH(e,f,g)+k[j+15]+mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE+th*BLKSIZE+j+15]; t2 = EP0(a)+MAJ(a,b,c); h = g; g = f; f = e; e = d+t1; d = c; c = b; b = a; a = t1+t2; #endif sregs[th*8+0] = a; sregs[th*8+1] = b; sregs[th*8+2] = c; sregs[th*8+3] = d; sregs[th*8+4] = e; sregs[th*8+5] = f; sregs[th*8+6] = g; sregs[th*8+7] = h; } } for (th=0; th<thnum; th++) { state[th*8+0] += sregs[th*8+0]; state[th*8+1] += sregs[th*8+1]; state[th*8+2] += sregs[th*8+2]; state[th*8+3] += sregs[th*8+3]; state[th*8+4] += sregs[th*8+4]; state[th*8+5] += sregs[th*8+5]; state[th*8+6] += sregs[th*8+6]; state[th*8+7] += sregs[th*8+7]; } }
3. 3. 20220202 3 ハッシュ計算には、面倒な演算が必要 case OP_MAJ: /* (((x) & (y))^((x) & (z))^((y) & (z))) */ ex1_outd = (r1&0xffffffff00000000LL) | (((r1 & r2)^(r1 & r3)^(r2 & r3))&0xffffffffLL); break; case OP_CH: /* (((x) & (y))^(~(x) & (z))) */ ex1_outd = (r1&0xffffffff00000000LL) | (((r1 & r2)^(~r1 & r3))&0xffffffffLL); break; case OP_ROTS: /* hi-32bit #define ROTRIGHT (((a) >> (b)) | ((a) << (32-(b)))) */ t2 = ex1_outd & 0xffffffff00000000LL; ro10 = r4>>32 & 0xff; ro11 = r4>>40 & 0xff; ro12 = r4>>48 & 0xff; t0 = ex1_outd & 0x00000000ffffffffLL; ro00 = r4 & 0xff; ro01 = r4>> 8 & 0xff; ro02 = r4>>16 & 0xff; ex2_outd = (((t2>>ro12|t2<<(32-ro12))^(t2>>ro11|t2<<(32-ro11))^(t2>>ro10|t2<<(32-ro10)))&0xffffffff00000000LL) |(((t0>>ro02|t0<<(32-ro02))^(t0>>ro01|t0<<(32-ro01))^(t0>>ro00|t0<<(32-ro00)))&0x00000000ffffffffLL); break;
4. 4. 20220202 4 ハッシュ計算には、面倒な演算が必要 for (i=0; i<ctx->mbuflen; i+=BLKSIZE) { /* 1データ流内の並列実行は不可能. 多数データ流のパイプライン実行のみ */ mtop = &mbuf[i/BLKSIZE*MAX_THNUM*BLKSIZE]; for (th=0; th<thnum; th++) { *(Ull*)&sregs[th*8+0] = (Ull)state[th*8+4]<<32|state[th*8+0]; *(Ull*)&sregs[th*8+2] = (Ull)state[th*8+5]<<32|state[th*8+1]; *(Ull*)&sregs[th*8+4] = (Ull)state[th*8+6]<<32|state[th*8+2]; *(Ull*)&sregs[th*8+6] = (Ull)state[th*8+7]<<32|state[th*8+3]; } #define sha256_core1(r, ofs) ¥ exe(OP_NOP, &AR[r][0], 0, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);¥ mop(OP_LDWR, 3, &md, mbase, ofs, MSK_D0, mtop, mlen, 0, 0, mptop, mlen); ¥ exe(OP_MAJ, &ep0maj, a, EXP_H1010, fb, EXP_H1010, gc, EXP_H1010, OP_ROTS, (2LL<<48)|(13LL<<40)|(22LL<<32), OP_NOP, 0);¥ exe(OP_NOP, &AR[r][2], 0, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);¥ mop(OP_LDWR, 3, &kd, kbase, ofs, MSK_D0, ktop, 64, 0, 0, NULL, 64); ¥ exe(OP_CH, &ep1ch, e, EXP_H3232, fb, EXP_H3232, gc, EXP_H3232, OP_ROTS, (6LL<<48)|(11LL<<40)|(25LL<<32), OP_NOP, 0);¥ exe(OP_NOP, &d0, hd, EXP_H1010, 0, EXP_H3210, 0, EXP_H3210, OP_AND, 0xffffffff00000000LL, OP_NOP, 0);¥ exe(OP_ADD, &t2, ep0maj, EXP_H3232, ep0maj, EXP_H1010, 0, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);¥ exe(OP_ADD, &y, kd, EXP_H3210, md, EXP_H3210, 0, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);¥ exe(OP_ADD3, &x, hd, EXP_H3232, ep1ch, EXP_H3232, ep1ch, EXP_H1010, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);¥ exe(OP_NOP, &hd, gc, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, 0, OP_NOP, 0);¥ exe(OP_NOP, &gc, fb, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, 0, OP_NOP, 0);¥ exe(OP_NOP, &fb, e, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, a, OP_NOP, 0);¥ exe(OP_ADD3, &a, t2, EXP_H3210, x, EXP_H1010, y, EXP_H1010, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0);¥ exe(OP_ADD3, &e, d0, EXP_H3210, x, EXP_H1010, y, EXP_H1010, OP_AND, 0xffffffff00000000LL, OP_NOP, 0) #define sha256_final(r) ¥ exe(OP_NOP, &ea, e, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_OR, a, OP_NOP, 0);¥ mop(OP_STR, 3, &ea, sregs0, th, MSK_W0, sregs, MAX_THNUM*8, 0, 0, NULL, MAX_THNUM*8); ¥ exe(OP_NOP, &AR[r][1], 0, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);¥ mop(OP_STR, 3, &fb, sregs2, th, MSK_W0, sregs, MAX_THNUM*8, 0, 0, NULL, MAX_THNUM*8); ¥ exe(OP_NOP, &AR[r][2], 0, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);¥ mop(OP_STR, 3, &gc, sregs4, th, MSK_W0, sregs, MAX_THNUM*8, 0, 0, NULL, MAX_THNUM*8); ¥ exe(OP_NOP, &AR[r][3], 0, EXP_H3210, 0, EXP_H3210, 0, EXP_H3210, OP_NOP, 0, OP_NOP, 0);¥ mop(OP_STR, 3, &hd, sregs6, th, MSK_W0, sregs, MAX_THNUM*8, 0, 0, NULL, MAX_THNUM*8) for (INIT1=1,LOOP1=DIV,j=0; LOOP1--; INIT1=0,j+=BLKSIZE/DIV*4) { mptop = (LOOP1==0)? mtop+MAX_THNUM*BLKSIZE*4:mtop; /* 最終回のみPLOAD */ //printf("--%08.8x %08.8x %08.8x %08.8x %08.8x %08.8x %08.8x %08.8x¥n", sregs[0*8+0], sregs[0*8+2], sregs[0*8+4], sregs[0*8+6], sregs[0*8+1], sregs[0*8+3], sregs[0*8+5], sregs[0*8+7]); //with-prefetch //EMAX5A begin imax mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { for (INIT0=1,LOOP0=thnum,th=(0-BLKSIZE*4)<<32|((0-32LL)&0xffffffff); LOOP0--; INIT0=0) { exe(OP_ADD, &th, INIT0?th:th, EXP_H3210, (BLKSIZE*4)<<32|32LL, EXP_H3210, 0, EXP_H3210, OP_AND, 0xffffffffffffffffLL, OP_NOP, 0); /* stage#0 */ exe(OP_NOP, &thm, th, EXP_H3232, 0, EXP_H3210, 0, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0); /* stage#1 */ exe(OP_ADD3, &mbase, mtop, EXP_H3210, thm, EXP_H3210, j, EXP_H3210, OP_NOP, 0, OP_NOP, 0); /* stage#2 */ mop(OP_LDR, 3, &a, sregs0, th, MSK_W0, sregs, MAX_THNUM*8, 0, 1, NULL, MAX_THNUM*8); /* stage#2 */ mop(OP_LDR, 3, &e, sregs0, th, MSK_W0, sregs, MAX_THNUM*8, 0, 1, NULL, MAX_THNUM*8); /* stage#2 */ exe(OP_ADD3, &kbase, imax_k, EXP_H3210, 0, EXP_H3210, j, EXP_H3210, OP_NOP, 0, OP_NOP, 0); /* stage#2 */ mop(OP_LDR, 3, &fb, sregs2, th, MSK_W0, sregs, MAX_THNUM*8, 0, 1, NULL, MAX_THNUM*8); /* stage#2 */ mop(OP_LDR, 3, &gc, sregs4, th, MSK_W0, sregs, MAX_THNUM*8, 0, 1, NULL, MAX_THNUM*8); /* stage#2 */ mop(OP_LDR, 3, &hd, sregs6, th, MSK_W0, sregs, MAX_THNUM*8, 0, 1, NULL, MAX_THNUM*8); /* stage#2 */ #if (DIV==4) sha256_core1( 3, 0); sha256_core1( 6, 4); sha256_core1( 9, 8); sha256_core1(12, 12); sha256_core1(15, 16); sha256_core1(18, 20); sha256_core1(21, 24); sha256_core1(24, 28); sha256_core1(27, 32); sha256_core1(30, 36); sha256_core1(33, 40); sha256_core1(36, 44); sha256_core1(39, 48); sha256_core1(42, 52); sha256_core1(45, 56); sha256_core1(48, 60); sha256_final(51); #endif } } //EMAX5A end } //EMAX5A drain_dirty_lmm for (th=0; th<thnum; th++) { state[th*8+0] += sregs[th*8+0]; state[th*8+1] += sregs[th*8+2]; state[th*8+2] += sregs[th*8+4]; state[th*8+3] += sregs[th*8+6]; state[th*8+4] += sregs[th*8+1]; state[th*8+5] += sregs[th*8+3]; state[th*8+6] += sregs[th*8+5]; state[th*8+7] += sregs[th*8+7]; } }
5. 5. 20220202 5 ハッシュ計算のコンパイル結果
6. 6. 20220202 6 FFTには、ダブルバッファリングが必要 BlockEnd = 1; for (BlockSize=2; BlockSize<=NumSamples; BlockSize<<=1) { for (i=0; i<NumSamples; i+=BlockSize) { for (j=i,n=0; n<BlockEnd; j++,n++) { k = j + BlockEnd; idx = n + BlockEnd; tr = art[idx]*RealOut[k] - ait[idx]*ImagOut[k]; ti = art[idx]*ImagOut[k] + ait[idx]*RealOut[k]; RealOut[k] = RealOut[j] - tr; ImagOut[k] = ImagOut[j] - ti; RealOut[j] += tr; ImagOut[j] += ti; } } BlockEnd = BlockSize; } 1段目 2段目 3段目
8. 8. 20220202 8 FFTのコンパイル結果
9. 9. 20220202 9 文字列検索 void strsearch(int i) { char *str = sstr[i]; int len = slen[i]; register size_t shift; register size_t pos = len - 1; char *found; while (pos < clen) { while (pos < clen && (shift = table[(unsigned char)target[pos]]) > 0) pos += shift; if (!shift) { if (!strncmp(str, &target[pos-len+1], len)) out0[i*clen+(pos-len+1)] = 0xff; pos++; } } } orig() { // "search"右端と同じ文字がbufpの右端にあれば手前から全体を比較 // たとえば右端が"r"なら，bufpを2進めてよい "rrrcharch" // ^-x // "rrrch" // xここからあるかも // たとえば右端が"s"なら，bufpを5進めてよい "aaaaaaasearch" // ^----x // xここからあるかも int i; for (i=0; i<snum; i++) { init_search(i); strsearch(i); } return 0; }
10. 10. 20220202 10 文字列検索 for (i=0; i<snum; i+=OMAP) { //EMAX5A begin search mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { //チップ方向は検索対象文書の大きさ方向 for (INIT0=1,LOOP0=loop,dmy=0; LOOP0--; INIT0=0) { //長さは32KB文字まで /* map#0 */ exe(OP_ADD, &t0[CHIP], t0[CHIP], EXP_H3210, 1LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x0000ffffffffffffLL, OP_NOP, 0LL); exe(OP_MCAS, &r00, slen0, EXP_H3210, 1, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r01, slen0, EXP_H3210, 2, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r02, slen0, EXP_H3210, 3, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r03, slen0, EXP_H3210, 4, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); mop(OP_LDBR, 1, &BR[1][0][1], t0[CHIP], 0, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][0][0], t0[CHIP], 1, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][1][1], t0[CHIP], 2, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][1][0], t0[CHIP], 3, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][2][1], t0[CHIP], 4, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][2][0], t0[CHIP], 5, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][3][1], t0[CHIP], 6, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); mop(OP_LDBR, 1, &BR[1][3][0], t0[CHIP], 7, MSK_D0, t0t[CHIP], dwi, 0, 0, (Ull)NULL, dwi); exe(OP_CMP_NE, &r16, c00, EXP_H3210, BR[1][0][1], EXP_H3210, 0LL, EXP_H3210, OP_AND, r00, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r17, c01, EXP_H3210, BR[1][0][0], EXP_H3210, 0LL, EXP_H3210, OP_AND, r01, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r18, c02, EXP_H3210, BR[1][1][1], EXP_H3210, 0LL, EXP_H3210, OP_AND, r02, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r19, c03, EXP_H3210, BR[1][1][0], EXP_H3210, 0LL, EXP_H3210, OP_AND, r03, OP_NOP, 0LL); // 1 if unmatch exe(OP_MCAS, &r04, slen0, EXP_H3210, 5, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r05, slen0, EXP_H3210, 6, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r06, slen0, EXP_H3210, 7, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_MCAS, &r07, slen0, EXP_H3210, 8, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); exe(OP_CMP_NE, &r20, c04, EXP_H3210, BR[1][2][1], EXP_H3210, 0LL, EXP_H3210, OP_AND, r04, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r21, c05, EXP_H3210, BR[1][2][0], EXP_H3210, 0LL, EXP_H3210, OP_AND, r05, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r22, c06, EXP_H3210, BR[1][3][1], EXP_H3210, 0LL, EXP_H3210, OP_AND, r06, OP_NOP, 0LL); // 1 if unmatch exe(OP_CMP_NE, &r23, c07, EXP_H3210, BR[1][3][0], EXP_H3210, 0LL, EXP_H3210, OP_AND, r07, OP_NOP, 0LL); // 1 if unmatch exe(OP_ADD3, &r10, r16, EXP_H3210, r17, EXP_H3210, r18, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); // exe(OP_ADD3, &r11, r19, EXP_H3210, r20, EXP_H3210, r21, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); // exe(OP_ADD, &r12, r22, EXP_H3210, r23, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); // exe(OP_ADD3, &r00, r10, EXP_H3210, r11, EXP_H3210, r12, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); // exe(OP_MCAS, &r31, 0LL, EXP_H3210, r00, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); // FF if match mop(OP_STBR, 3, &r31, r0[CHIP]++, 0, MSK_D0, r0t[CHIP], dwo, 0, 0, (Ull)NULL, dwo); /* map#1 */ : /* map#8 */ : } } //EMAX5A end //EMAX5A drain_dirty_lmm }
11. 11. 20220202 11 文字列検索のコンパイル結果
12. 12. 20220202 12 今回のおさらい

### Notes de l'éditeur

• 様々なアプリケーションを取りあげて、アイマックスのポテンシャルを説明するシリーズです。第9回は、ハッシュ計算と、FFTと、文字列検索です。
• ハッシュ計算には、ローテートや排他論理和がたくさん使われます。これは、SHA256です。個々の演算は簡単ですが、とにかく、演算の数がとても多いです。右うえの図は、ハッシュ計算専用ハードウェアです。専用ハードウェアなら、電力効率を最大化できます。でも、半導体を作るコストが、とても高くなっているので、開発費を回収するためには、少し違った用途にも使える必要があります。ある程度、プログラムで機能を変更できる必要があるということです。この点、CGRAは、CPUと専用ハードウェアの中間にあります。
• さっきのプログラムが使っていた、MAJ、CH、EP0の実体は、この計算です。ローテートと、排他論理和の、かたまりであることがわかります。そもそも、ハッシュ計算というのは、なるべく元のデータの情報量を減らさずに、原型をとどめなくなるまで、ミキサーにかける作業です。だから、情報量がなるべく減らない、ローテートと、排他論理和をたくさん使います。
• 普通のCPUでは、ローテートに1命令、論理演算に1命令を使うので、とても時間がかかります。一方、アイマックスは、ハッシュ計算を高密度に実行するために、5入力演算器の初段に、MAJとCH、2段目に、ROTSハードウェアを持っています。赤字部分が、MAJとROTS、CHとROTSを組み合わせている記述です。最初のCプログラムの赤字部分、1行を実行するのに、3個の物理ユニットを使うので、64ユニットには、16行分を写像できます。ちょうど、最初のプログラムと同じ構造になります。
• コンパイル結果です。5入力演算器が、総動員されていることがわかります。
• 次は、FFTです。時系列データから、周波数成分を取り出すのに便利です。上の図は、計算結果の例です。横軸が周波数です。特定の周波数のところに、波形のピークが来ています。FFTのコードは、シンプルです。右の図のように、バタフライ演算とよぶ、ログN段の、規則的な積和演算を繰り返します。ただし、データの参照順は、ステージが進むにつれて、変化していきます。さて、前に説明したマージソートでは、ローカルメモリのダブルバッファリング機能による、2レベルパイプライン処理を使いました。FFTでも、ログN段に対して、同じ機能を使います。
• アイマックスのコードです。青字部分は、乗数をロードしている部分です。そして、赤字部分は、ストアとロードが組になっています。コンパイラは、ローカルメモリの領域長が0であることを検出して、ダブルバッファリング機能に写像します。4096要素のFFTの写像に、52ユニットを使っています。
• コンパイル結果です。FFTでも、5入力演算器が、総動員されていることがわかります。
• 最後は、文字列検索です。これは、CPUのコードです。
• これが、アイマックスのコードです。MCASは、コンペアアンドセットです。第1オペランドが第2オペランドより小さければ0、それ以外はFFを代入します。これをマスクとして使い、一般的な1ワード比較命令を、文字列比較機能として使っています。このように、普通にC言語でプログラムできるだけでは、CGRAを使いこなすことはできません。柔軟かつ大胆な発想が必要です。エンジニアの0.01％ということです。
• コンパイル結果です。文字列検索でも、5入力演算器が、総動員されていることがわかります。
• 今回は、ブロックチェインにつかわれるハッシュ計算と、FFTと、文字列検索を題材に、いろいろ説明しました。では、今回はここまでです。おつかれさま。