SlideShare uma empresa Scribd logo
1 de 10
CPU GPU
Ultimate CGRA w/ high-speed compiler
CGRA for Energy-efficient Cryptography
Beyond-Neuromorphic Systems
Non-Deterministic Computing
1
ナレータ VOICEVOX:もち子(cv 明日葉よもぎ)
はらぺこエンジニアに贈るCGRAの世界2022
(7. 逆行列編)
スパコンからIoTまで 省エネ社会に
AI+BCだけじゃない超効率計算手法
20220202
2
逆行列は、連立一次方程式の特殊ケースで求まる
連立一次方程式
LU分解
前進消去
後退代入
20220202
3
逆行列は、連立一次方程式の特殊ケースで求まる
連立一次方程式:Ax=bを解く
逆行列:bの列数を増やして単位行列にする
xの列数が増えたものが逆行列
/* LU分解 */
for (i=0; i<M+1; i++)
p[i] = i;
for (i=0; i<M; i++) {
pmax = 0.0;
k = -1;
for (j=i; j<M; j++) {
if (pmax < fabsf(A[p[j]*M+i])) {
pmax = fabsf(A[p[j]*M+i]);
k = j;
}
}
if (k == -1) {
fprintf(stderr, "can't solven");
exit(1);
}
j = p[k]; p[k] = p[i]; p[i] = j;
A[p[i]*M+i] = 1.0/A[p[i]*M+i];
for (j=i+1; j<M; j++) {
A[p[j]*M+i] *= A[p[i]*M+i];
for (k=i+1; k<M; k++)
A[p[j]*M+k] -= A[p[j]*M+i]*A[p[i]*M+k];
}
}
/* 逆行列求める */
for (i=0; i<M; i++) {
for (j=0; j<M; j++)
b[p[j]] = (i==j)?1.0:0.0;
/*for (j=1; j<M; j++) { *//* 通常の連立一時方程式の場合*/
for (j=i+1; j<M; j++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでj=i+1から開始 */
/*for (k=0; k<j; k++) *//* 通常の連立一時方程式の場合*/
for (k=i; k<j; k++) /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでk=iから開始 */
b[p[j]] -= A[p[j]*M+k]*b[p[k]];
}
for (j=M-1; j>=0; j--) {
for (k=M-1; k>j; k--)
b[p[j]] -= A[p[j]*M+k]*x[k];
inv0[j*M+p[i]] = x[j] = b[p[j]]*A[p[j]*M+j];
}
}
20220202
4
逆行列には、ローカルメモリ自己更新
/* LU分解 */
for (i=0; i<M+1; i++)
p[i] = i;
for (i=0; i<M; i++) { /* 列方向 */
pmax = 0.0;
k = -1;
for (j=i; j<M; j++) { /* 行方向に探索 */
if (pmax < fabsf(A[j*M+i])) {
pmax = fabsf(A[j*M+i]);
k = j;
}
}
if (k == -1) {
fprintf(stderr, "can't solven");
exit(1);
}
j = p[k]; p[k] = p[i]; p[i] = j;
for (j=0; j<M; j++) { /* real pivotting */ /*★*/
tmp = A[k*M+j]; A[k*M+j] = A[i*M+j]; A[i*M+j] = tmp;/*★*/
} /*★*/
A[i*M+i] = 1.0/A[i*M+i]; /*★*/
for (j=i+1; j<M; j++) /* 行方向 */
A[j*M+i] *= A[i*M+i];
Uint *top = &A[i*M+i];
Uint *topw = (Ull)top;
Uint len = M-i;
Uint len2 = len+(RMGRP-1)*M;
Uint grp;
/* FPGA実機でj-loopの最終(len=1)が動かないので,ついでにARMのほうが速そうなlenをARMで実行 */
if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */
for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (h=0; h<H; h++) { /* vertical (parallel) execution */
for (grp=0; grp<RMGRP; grp++) {
for (k=0; k<M-(i+1); k++) { /* 最内列方向 */
if (j+h*NCHIP*RMGRP+CHIP*RMGRP+grp<M) A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i+1+k]
-= A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i]*A[i*M+i+1+k];
}
}
}
}
}
}
else {
for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */
//EMAX5A begin inv_x1 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT1=1,LOOP1=RMGRP,rofs=0-M*4; LOOP1--; INIT1=0) { /* stage#0 *//* mapped to FOR() on BR[63][1][0] */
for (INIT0=1,LOOP0=M-(i+1),cofs=0; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */
exe(OP_ADD, &cofs, INIT0?cofs:cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */
exe(OP_ADD, &rofs, rofs, EXP_H3210, INIT0?M*4:0, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#0 */
exe(OP_ADD, &oofs, rofs, EXP_H3210, cofs, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#1 */
/***************************/
/* + - - - - - - - - - - - */ /* A[p[i]] 先頭行 */ /* 先頭行はi更新まで再利用可能 */
/* | * > > > > > > > > > > */ /* A[p[j]] 次行から引く */ /* 1行をLMMに写像 */
/* | v + - - - - - - - - - */
/* | v | * > > > > > > > > */ /* M/60を収容してi更新までj+=60を繰り返す *//* 行番号比較とcstによる端数制御 */
/* | v | v + - - - - - - - */ /* + CHIP#0 h=0 grp=0 */
/* | v | v - + - - - - - - */ /* + CHIP#0 h=0 grp=1 */
/* | v | v - - + - - - - - */ /* + CHIP#1 h=0 grp=0 */
/* | v | v - - - + - - - - */ /* + CHIP#1 h=0 grp=1 */
/* | v | v - - - - + - - - */ /* + CHIP#0 h=1 grp=0 */
/* | v | v - - - - - + - - */ /* + CHIP#0 h=1 grp=1 */
/* | v | v - - - - - - + - */ /* + CHIP#1 h=1 grp=0 */
/* | v | v - - - - - - - + */ /* + CHIP#1 h=1 grp=1 */
/***************************/ /* 最大60行まで写像可能 */
/* FOLDING時は,少なくとも第0列がFOLDINGであることが必要(conv-c2c仕様) */
/* CEXEにも関わらずSTWRの無意味なLMM入れ換えが発生するため,A[M][*](枠外領域)を使用 */ /* OK exe-loop */
exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#1 LD */
mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#2 | */
mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */
mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */
exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#2 | AR[1] | */
mop(OP_STWR,ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2); /* stage#2 | + ST v */
#if (H>1) /* *--------- BR[2] */
exe(OP_CMP_LT, &cc1, l01[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 LD */
mop(OP_LDWR, 1, &BR[3][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#3 | */
mop(OP_LDWR, 1, &BR[3][0][1], d01[CHIP], oofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */
mop(OP_LDWR, 1, &BR[3][1][1], d01[CHIP], rofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */
exe(OP_FMS, &AR[3][0], BR[3][0][1], EXP_H3210, BR[3][1][1], EXP_H3210, BR[3][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#3 | AR[2] | */
mop(OP_STWR,ex0, &AR[3][0], oofs, d01[CHIP], MSK_D0, d01w[CHIP], len2, 0, 1, NULL, len2); /* stage#3 | + ST v */
#if (H>2) /* *--------- BR[3] */
exe(OP_CMP_LT, &cc0, l02[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 LD */
mop(OP_LDWR, 1, &BR[4][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#1 stage#4 | */
mop(OP_LDWR, 1, &BR[4][0][1], d02[CHIP], oofs, MSK_W0, d02w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#4 +-> | */
mop(OP_LDWR, 1, &BR[4][1][1], d02[CHIP], rofs, MSK_W0, d02w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#4 +-> | */
exe(OP_FMS, &AR[4][0], BR[4][0][1], EXP_H3210, BR[4][1][1], EXP_H3210, BR[4][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#4 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#4 | AR[3] | */
mop(OP_STWR,ex0, &AR[4][0], oofs, d02[CHIP], MSK_D0, d02w[CHIP], len2, 0, 1, NULL, len2); /* stage#4 | + ST v */
#if (H>3) /* *--------- BR[4] */
exe(OP_CMP_LT, &cc1, l03[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#4 LD */
mop(OP_LDWR, 1, &BR[5][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#1 stage#5 | */
mop(OP_LDWR, 1, &BR[5][0][1], d03[CHIP], oofs, MSK_W0, d03w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#5 +-> | */
mop(OP_LDWR, 1, &BR[5][1][1], d03[CHIP], rofs, MSK_W0, d03w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#5 +-> | */
exe(OP_FMS, &AR[5][0], BR[5][0][1], EXP_H3210, BR[5][1][1], EXP_H3210, BR[5][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#5 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#5 | AR[4] | */
mop(OP_STWR,ex0, &AR[5][0], oofs, d03[CHIP], MSK_D0, d03w[CHIP], len2, 0, 1, NULL, len2); /* stage#5 | + ST v */
#endif
#endif
#endif
}
}
}
//EMAX5A end
} /* j-loop */
//EMAX5A drain_dirty_lmm
} /* else */
}
20220202
5
逆行列には、ローカルメモリ自己更新
for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */
//EMAX5A begin inv_x1 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT1=1,LOOP1=RMGRP,rofs=0-M*4; LOOP1--; INIT1=0) { /* stage#0 *//* mapped to FOR() on BR[63][1][0] */
for (INIT0=1,LOOP0=M-(i+1),cofs=0; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */
exe(OP_ADD, &cofs, INIT0?cofs:cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */
exe(OP_ADD, &rofs, rofs, EXP_H3210, INIT0?M*4:0, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#0 */
exe(OP_ADD, &oofs, rofs, EXP_H3210, cofs, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#1 */
/***************************/
/* + - - - - - - - - - - - */ /* A[p[i]] 先頭行 */ /* 先頭行はi更新まで再利用可能 */
/* | * > > > > > > > > > > */ /* A[p[j]] 次行から引く */ /* 1行をLMMに写像 */
/* | v + - - - - - - - - - */
/* | v | * > > > > > > > > */ /* M/60を収容してi更新までj+=60を繰り返す *//* 行番号比較とcstによる端数制御 */
/* | v | v + - - - - - - - */ /* + CHIP#0 h=0 grp=0 */
/* | v | v - + - - - - - - */ /* + CHIP#0 h=0 grp=1 */
/* | v | v - - + - - - - - */ /* + CHIP#1 h=0 grp=0 */
/* | v | v - - - + - - - - */ /* + CHIP#1 h=0 grp=1 */
/* | v | v - - - - + - - - */ /* + CHIP#0 h=1 grp=0 */
/* | v | v - - - - - + - - */ /* + CHIP#0 h=1 grp=1 */
/* | v | v - - - - - - + - */ /* + CHIP#1 h=1 grp=0 */
/* | v | v - - - - - - - + */ /* + CHIP#1 h=1 grp=1 */
/***************************/ /* 最大60行まで写像可能 */
/* FOLDING時は,少なくとも第0列がFOLDINGであることが必要(conv-c2c仕様) */
/* CEXEにも関わらずSTWRの無意味なLMM入れ換えが発生するため,A[M][*](枠外領域)を使用 */ /* OK exe-loop */
exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#1 LD */
mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#2 | */
mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */
mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */
exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#2 | AR[1] | */
mop(OP_STWR,ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2); /* stage#2 | + ST v */
#if (H>1) /* *--------- BR[2] */
exe(OP_CMP_LT, &cc1, l01[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 LD */
mop(OP_LDWR, 1, &BR[3][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#3 | */
mop(OP_LDWR, 1, &BR[3][0][1], d01[CHIP], oofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */
mop(OP_LDWR, 1, &BR[3][1][1], d01[CHIP], rofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */
exe(OP_FMS, &AR[3][0], BR[3][0][1], EXP_H3210, BR[3][1][1], EXP_H3210, BR[3][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 | ■■■ | 1.0 */
cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#3 | AR[2] | */
mop(OP_STWR,ex0, &AR[3][0], oofs, d01[CHIP], MSK_D0, d01w[CHIP], len2, 0, 1, NULL, len2); /* stage#3 | + ST v */
#if (H>2) /* *--------- BR[3] */
if (j+h*NCHIP*RMGRP+CHIP*RMGRP+grp<M)
A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i+1+k]
-= A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i]*A[i*M+i+1+k];
20220202
6
条件付きストア機能を使う
exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL,
mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len);
mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2);
mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2);
exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1],
cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa );
mop(OP_STWR, ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2);
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
20220202
7
逆行列には、ローカルメモリ自己更新
/* 前進消去 */
for (i=0; i<M; i++) { /* 列方向 */
for (j=0; j<M; j++) /* 行方向 */
b[i*M+j] = (i==j)?1.0:0.0;
}
for (i=0; i<M; i+=NCHIP*H) { /* 列方向 */
/*for (j=1; j<M; j++) { *//*通常の連立一時方程式の場合*/
for (j=i+1; j<M; j++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでj=i+1から開始 */
Uint *top = &A[j*M+i]; /* A[p[j]*M+k] */
Uint *topw = (Ull)top;
/*Uint len = (j+1)/2;*/
Uint len = j-i;/* bが単位行列の場合,k<iではb[]==0なのでk=iから開始 */
/********************************************/
if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (h=0; h<H; h++) { /* vertical (parallel) execution */
/*for (k=0; k<j; k++) { *//*通常の連立一時方程式の場合*/
for (k=i; k<j; k++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでk=iから開始 */
b[(i+CHIP*H+h)*M+j] -= A[j*M+k]*b[(i+CHIP*H+h)*M+k];
}
}
}
}
else {
Uint jc = j-i;
//EMAX5A begin inv_x2 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT0=1,LOOP0=jc,cofs=0-4; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */
exe(OP_ADD, &cofs, cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */
mop(OP_LDWR, 1, &Ajk, top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[j]*M+k] *//* stage#1.0 */
mop(OP_LDWR, 1, &BR[1][3][1], t000[CHIP], cofs, MSK_W0, t000w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#1.3 +->xxx LD */
mop(OP_LDWR, 1, &b000, d000[CHIP], 0, MSK_W0, d000w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#2.0 | ■■■ | */
exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[1][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#2.0 +- xxx+ST v */
mop(OP_STWR, 1, &b000, 0, d000[CHIP], MSK_D0, d000w[CHIP], 1, 0, 1, NULL, 1); /* stage#2.0 +--------- xxx */
#if (H>1)
mop(OP_LDWR, 1, &BR[2][3][1], t010[CHIP], cofs, MSK_W0, t010w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#2.3 +->xxx LD */
mop(OP_LDWR, 1, &b000, d010[CHIP], 0, MSK_W0, d010w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#3.0 | ■■■ | */
exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[2][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#3.0 +- xxx+ST v */
mop(OP_STWR, 1, &b000, 0, d010[CHIP], MSK_D0, d010w[CHIP], 1, 0, 1, NULL, 1); /* stage#3.0 +--------- xxx */
#if (H>2)
:
#endif
#endif
}
}
//EMAX5A end
//EMAX5A drain_dirty_lmm
} /* else */
/********************************************/
} /* j-loop */
}
20220202
8
逆行列には、ローカルメモリ自己更新
/* 後退代入 */
for (i=0; i<M; i+=NCHIP*H) { /* 列方向 */
for (j=M-1; j>=0; j--) { /* 行方向 */
if (j<M-1) {
Uint *top = &A[j*M+j+1]; /* A[p[j]*M+k] */
Uint *topw = (Ull)top;
Uint len = M-j-1;
/********************************************/
if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (h=0; h<H; h++) { /* vertical (parallel) execution */
for (k=M-1; k>j; k--) { /* 最内列方向 */
b[(i+CHIP*H+h)*M+j] -= A[j*M+k]*x[(i+CHIP*H+h)*M+k];
}
}
}
}
else {
Uint jc = M-j-1;
//EMAX5A begin inv_x3 mapdist=0
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (INIT0=1,LOOP0=jc,cofs=jc*4; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */
exe(OP_ADD, &cofs, cofs, EXP_H3210, -4, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */
mop(OP_LDWR, 1, &Ajk, top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[j]*M+k] *//* */
mop(OP_LDWR, 1, &BR[1][3][1], t000[CHIP], cofs, MSK_W0, t000w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#1.3 +->xxx LD *//*read-modify-w*/
mop(OP_LDWR, 1, &b000, d000[CHIP], 0, MSK_W0, d000w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#2.0 | ■■■ | */
exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[1][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#2.0 +- xxx+ST v */
mop(OP_STWR, 1, &b000, 0, d000[CHIP], MSK_D0, d000w[CHIP], 1, 0, 1, NULL, 1); /* stage#2.0 +--------- xxx */
#if (H>1)
mop(OP_LDWR, 1, &BR[2][3][1], t010[CHIP], cofs, MSK_W0, t010w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#2.3 +->xxx LD *//*read-modify-w*/
mop(OP_LDWR, 1, &b000, d010[CHIP], 0, MSK_W0, d010w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#3.0 | ■■■ | */
exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[2][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#3.0 +- xxx+ST v */
mop(OP_STWR, 1, &b000, 0, d010[CHIP], MSK_D0, d010w[CHIP], 1, 0, 1, NULL, 1); /* stage#3.0 +--------- xxx */
#if (H>2)
:
#endif
#endif
}
}
//EMAX5A end
//EMAX5A drain_dirty_lmm
} /* else */
/********************************************/
} /* if (j<M-1) */
for (CHIP=0; CHIP<NCHIP; CHIP++) {
for (h=0; h<H; h++) { /* vertical (parallel) execution */
inv1[j*M+p[i+CHIP*H+h]] = x[(i+CHIP*H+h)*M+j] = A[j*M+j]*b[(i+CHIP*H+h)*M+j]; /* PIOにてLMMのx[i*M+j]を直接更新 *//* iはそのままで,jを切替え */
}
}
} /* j-loop */
}
20220202
9
コンパイル結果
20220202
10
今回のおさらい

Mais conteúdo relacionado

Semelhante a PBL1-v1-007j.pptx

Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたMITSUNARI Shigeo
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会7shi
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenMITSUNARI Shigeo
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチMasami Ichikawa
 
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsPL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsKohei KaiGai
 
AVX命令を用いたLJの力計算のSIMD化
AVX命令を用いたLJの力計算のSIMD化AVX命令を用いたLJの力計算のSIMD化
AVX命令を用いたLJの力計算のSIMD化Hiroshi Watanabe
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングKiwamu Okabe
 
x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTtakesako
 
64-bit SML# への壁
64-bit SML# への壁64-bit SML# への壁
64-bit SML# への壁chunjp
 
Processing workshop v3.0
Processing workshop v3.0Processing workshop v3.0
Processing workshop v3.0Wataru Kani
 
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目hecomi
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部NVIDIA Japan
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件yaegashi
 
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎Insight Technology, Inc.
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)Takeshi Yamamuro
 
Designing video game hardware in verilog
Designing video game hardware in verilogDesigning video game hardware in verilog
Designing video game hardware in verilogAtsuki Takahashi
 

Semelhante a PBL1-v1-007j.pptx (20)

Slide
SlideSlide
Slide
 
Intro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみたIntro to SVE 富岳のA64FXを触ってみた
Intro to SVE 富岳のA64FXを触ってみた
 
マーク&スイープ勉強会
マーク&スイープ勉強会マーク&スイープ勉強会
マーク&スイープ勉強会
 
フラグを愛でる
フラグを愛でるフラグを愛でる
フラグを愛でる
 
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgenIntel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
Intel AVX-512/富岳SVE用SIMDコード生成ライブラリsimdgen
 
x86とコンテキストスイッチ
x86とコンテキストスイッチx86とコンテキストスイッチ
x86とコンテキストスイッチ
 
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsPL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database Analytics
 
AVX命令を用いたLJの力計算のSIMD化
AVX命令を用いたLJの力計算のSIMD化AVX命令を用いたLJの力計算のSIMD化
AVX命令を用いたLJの力計算のSIMD化
 
HaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミングHaskellではじめるCortex-M3組込みプログラミング
HaskellではじめるCortex-M3組込みプログラミング
 
x86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNTx86x64 SSE4.2 POPCNT
x86x64 SSE4.2 POPCNT
 
ILE-RPG Study 001
ILE-RPG Study 001ILE-RPG Study 001
ILE-RPG Study 001
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 
64-bit SML# への壁
64-bit SML# への壁64-bit SML# への壁
64-bit SML# への壁
 
Processing workshop v3.0
Processing workshop v3.0Processing workshop v3.0
Processing workshop v3.0
 
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
Node.js × 音声認識 - 東京Node学園 2012 LT枠 6番目
 
20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部20190625 OpenACC 講習会 第3部
20190625 OpenACC 講習会 第3部
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎
[data analytics showcase] B12: サーバー1,000台を監視するということ by 株式会社インサイトテクノロジー 小幡 一郎
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
Designing video game hardware in verilog
Designing video game hardware in verilogDesigning video game hardware in verilog
Designing video game hardware in verilog
 

Mais de NAIST

PBL1-v1-200j.pptx
PBL1-v1-200j.pptxPBL1-v1-200j.pptx
PBL1-v1-200j.pptxNAIST
 
PBL1-v1-200e.pptx
PBL1-v1-200e.pptxPBL1-v1-200e.pptx
PBL1-v1-200e.pptxNAIST
 
PBL1-v1-100j.pptx
PBL1-v1-100j.pptxPBL1-v1-100j.pptx
PBL1-v1-100j.pptxNAIST
 
PBL1-v1-100e.pptx
PBL1-v1-100e.pptxPBL1-v1-100e.pptx
PBL1-v1-100e.pptxNAIST
 
PBL1-v1-014j.pptx
PBL1-v1-014j.pptxPBL1-v1-014j.pptx
PBL1-v1-014j.pptxNAIST
 
PBL1-v1-014e.pptx
PBL1-v1-014e.pptxPBL1-v1-014e.pptx
PBL1-v1-014e.pptxNAIST
 
PBL1-v1-013j.pptx
PBL1-v1-013j.pptxPBL1-v1-013j.pptx
PBL1-v1-013j.pptxNAIST
 
PBL1-v1-013e.pptx
PBL1-v1-013e.pptxPBL1-v1-013e.pptx
PBL1-v1-013e.pptxNAIST
 
PBL1-v1-012j.pptx
PBL1-v1-012j.pptxPBL1-v1-012j.pptx
PBL1-v1-012j.pptxNAIST
 
PBL1-v1-012e.pptx
PBL1-v1-012e.pptxPBL1-v1-012e.pptx
PBL1-v1-012e.pptxNAIST
 
PBL1-v1-005j.pptx
PBL1-v1-005j.pptxPBL1-v1-005j.pptx
PBL1-v1-005j.pptxNAIST
 
PBL1-v1-004j.pptx
PBL1-v1-004j.pptxPBL1-v1-004j.pptx
PBL1-v1-004j.pptxNAIST
 
PBL1-v1-002j.pptx
PBL1-v1-002j.pptxPBL1-v1-002j.pptx
PBL1-v1-002j.pptxNAIST
 
PBL1-v1-001j.pptx
PBL1-v1-001j.pptxPBL1-v1-001j.pptx
PBL1-v1-001j.pptxNAIST
 
PBL1-v0-200j.pptx
PBL1-v0-200j.pptxPBL1-v0-200j.pptx
PBL1-v0-200j.pptxNAIST
 

Mais de NAIST (15)

PBL1-v1-200j.pptx
PBL1-v1-200j.pptxPBL1-v1-200j.pptx
PBL1-v1-200j.pptx
 
PBL1-v1-200e.pptx
PBL1-v1-200e.pptxPBL1-v1-200e.pptx
PBL1-v1-200e.pptx
 
PBL1-v1-100j.pptx
PBL1-v1-100j.pptxPBL1-v1-100j.pptx
PBL1-v1-100j.pptx
 
PBL1-v1-100e.pptx
PBL1-v1-100e.pptxPBL1-v1-100e.pptx
PBL1-v1-100e.pptx
 
PBL1-v1-014j.pptx
PBL1-v1-014j.pptxPBL1-v1-014j.pptx
PBL1-v1-014j.pptx
 
PBL1-v1-014e.pptx
PBL1-v1-014e.pptxPBL1-v1-014e.pptx
PBL1-v1-014e.pptx
 
PBL1-v1-013j.pptx
PBL1-v1-013j.pptxPBL1-v1-013j.pptx
PBL1-v1-013j.pptx
 
PBL1-v1-013e.pptx
PBL1-v1-013e.pptxPBL1-v1-013e.pptx
PBL1-v1-013e.pptx
 
PBL1-v1-012j.pptx
PBL1-v1-012j.pptxPBL1-v1-012j.pptx
PBL1-v1-012j.pptx
 
PBL1-v1-012e.pptx
PBL1-v1-012e.pptxPBL1-v1-012e.pptx
PBL1-v1-012e.pptx
 
PBL1-v1-005j.pptx
PBL1-v1-005j.pptxPBL1-v1-005j.pptx
PBL1-v1-005j.pptx
 
PBL1-v1-004j.pptx
PBL1-v1-004j.pptxPBL1-v1-004j.pptx
PBL1-v1-004j.pptx
 
PBL1-v1-002j.pptx
PBL1-v1-002j.pptxPBL1-v1-002j.pptx
PBL1-v1-002j.pptx
 
PBL1-v1-001j.pptx
PBL1-v1-001j.pptxPBL1-v1-001j.pptx
PBL1-v1-001j.pptx
 
PBL1-v0-200j.pptx
PBL1-v0-200j.pptxPBL1-v0-200j.pptx
PBL1-v0-200j.pptx
 

PBL1-v1-007j.pptx

  • 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 (7. 逆行列編) スパコンからIoTまで 省エネ社会に AI+BCだけじゃない超効率計算手法
  • 3. 20220202 3 逆行列は、連立一次方程式の特殊ケースで求まる 連立一次方程式:Ax=bを解く 逆行列:bの列数を増やして単位行列にする xの列数が増えたものが逆行列 /* LU分解 */ for (i=0; i<M+1; i++) p[i] = i; for (i=0; i<M; i++) { pmax = 0.0; k = -1; for (j=i; j<M; j++) { if (pmax < fabsf(A[p[j]*M+i])) { pmax = fabsf(A[p[j]*M+i]); k = j; } } if (k == -1) { fprintf(stderr, "can't solven"); exit(1); } j = p[k]; p[k] = p[i]; p[i] = j; A[p[i]*M+i] = 1.0/A[p[i]*M+i]; for (j=i+1; j<M; j++) { A[p[j]*M+i] *= A[p[i]*M+i]; for (k=i+1; k<M; k++) A[p[j]*M+k] -= A[p[j]*M+i]*A[p[i]*M+k]; } } /* 逆行列求める */ for (i=0; i<M; i++) { for (j=0; j<M; j++) b[p[j]] = (i==j)?1.0:0.0; /*for (j=1; j<M; j++) { *//* 通常の連立一時方程式の場合*/ for (j=i+1; j<M; j++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでj=i+1から開始 */ /*for (k=0; k<j; k++) *//* 通常の連立一時方程式の場合*/ for (k=i; k<j; k++) /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでk=iから開始 */ b[p[j]] -= A[p[j]*M+k]*b[p[k]]; } for (j=M-1; j>=0; j--) { for (k=M-1; k>j; k--) b[p[j]] -= A[p[j]*M+k]*x[k]; inv0[j*M+p[i]] = x[j] = b[p[j]]*A[p[j]*M+j]; } }
  • 4. 20220202 4 逆行列には、ローカルメモリ自己更新 /* LU分解 */ for (i=0; i<M+1; i++) p[i] = i; for (i=0; i<M; i++) { /* 列方向 */ pmax = 0.0; k = -1; for (j=i; j<M; j++) { /* 行方向に探索 */ if (pmax < fabsf(A[j*M+i])) { pmax = fabsf(A[j*M+i]); k = j; } } if (k == -1) { fprintf(stderr, "can't solven"); exit(1); } j = p[k]; p[k] = p[i]; p[i] = j; for (j=0; j<M; j++) { /* real pivotting */ /*★*/ tmp = A[k*M+j]; A[k*M+j] = A[i*M+j]; A[i*M+j] = tmp;/*★*/ } /*★*/ A[i*M+i] = 1.0/A[i*M+i]; /*★*/ for (j=i+1; j<M; j++) /* 行方向 */ A[j*M+i] *= A[i*M+i]; Uint *top = &A[i*M+i]; Uint *topw = (Ull)top; Uint len = M-i; Uint len2 = len+(RMGRP-1)*M; Uint grp; /* FPGA実機でj-loopの最終(len=1)が動かないので,ついでにARMのほうが速そうなlenをARMで実行 */ if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */ for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */ for (CHIP=0; CHIP<NCHIP; CHIP++) { for (h=0; h<H; h++) { /* vertical (parallel) execution */ for (grp=0; grp<RMGRP; grp++) { for (k=0; k<M-(i+1); k++) { /* 最内列方向 */ if (j+h*NCHIP*RMGRP+CHIP*RMGRP+grp<M) A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i+1+k] -= A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i]*A[i*M+i+1+k]; } } } } } } else { for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */ //EMAX5A begin inv_x1 mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { for (INIT1=1,LOOP1=RMGRP,rofs=0-M*4; LOOP1--; INIT1=0) { /* stage#0 *//* mapped to FOR() on BR[63][1][0] */ for (INIT0=1,LOOP0=M-(i+1),cofs=0; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */ exe(OP_ADD, &cofs, INIT0?cofs:cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */ exe(OP_ADD, &rofs, rofs, EXP_H3210, INIT0?M*4:0, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#0 */ exe(OP_ADD, &oofs, rofs, EXP_H3210, cofs, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#1 */ /***************************/ /* + - - - - - - - - - - - */ /* A[p[i]] 先頭行 */ /* 先頭行はi更新まで再利用可能 */ /* | * > > > > > > > > > > */ /* A[p[j]] 次行から引く */ /* 1行をLMMに写像 */ /* | v + - - - - - - - - - */ /* | v | * > > > > > > > > */ /* M/60を収容してi更新までj+=60を繰り返す *//* 行番号比較とcstによる端数制御 */ /* | v | v + - - - - - - - */ /* + CHIP#0 h=0 grp=0 */ /* | v | v - + - - - - - - */ /* + CHIP#0 h=0 grp=1 */ /* | v | v - - + - - - - - */ /* + CHIP#1 h=0 grp=0 */ /* | v | v - - - + - - - - */ /* + CHIP#1 h=0 grp=1 */ /* | v | v - - - - + - - - */ /* + CHIP#0 h=1 grp=0 */ /* | v | v - - - - - + - - */ /* + CHIP#0 h=1 grp=1 */ /* | v | v - - - - - - + - */ /* + CHIP#1 h=1 grp=0 */ /* | v | v - - - - - - - + */ /* + CHIP#1 h=1 grp=1 */ /***************************/ /* 最大60行まで写像可能 */ /* FOLDING時は,少なくとも第0列がFOLDINGであることが必要(conv-c2c仕様) */ /* CEXEにも関わらずSTWRの無意味なLMM入れ換えが発生するため,A[M][*](枠外領域)を使用 */ /* OK exe-loop */ exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#1 LD */ mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#2 | */ mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */ mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */ exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#2 | AR[1] | */ mop(OP_STWR,ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2); /* stage#2 | + ST v */ #if (H>1) /* *--------- BR[2] */ exe(OP_CMP_LT, &cc1, l01[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 LD */ mop(OP_LDWR, 1, &BR[3][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#3 | */ mop(OP_LDWR, 1, &BR[3][0][1], d01[CHIP], oofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */ mop(OP_LDWR, 1, &BR[3][1][1], d01[CHIP], rofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */ exe(OP_FMS, &AR[3][0], BR[3][0][1], EXP_H3210, BR[3][1][1], EXP_H3210, BR[3][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#3 | AR[2] | */ mop(OP_STWR,ex0, &AR[3][0], oofs, d01[CHIP], MSK_D0, d01w[CHIP], len2, 0, 1, NULL, len2); /* stage#3 | + ST v */ #if (H>2) /* *--------- BR[3] */ exe(OP_CMP_LT, &cc0, l02[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 LD */ mop(OP_LDWR, 1, &BR[4][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#1 stage#4 | */ mop(OP_LDWR, 1, &BR[4][0][1], d02[CHIP], oofs, MSK_W0, d02w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#4 +-> | */ mop(OP_LDWR, 1, &BR[4][1][1], d02[CHIP], rofs, MSK_W0, d02w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#4 +-> | */ exe(OP_FMS, &AR[4][0], BR[4][0][1], EXP_H3210, BR[4][1][1], EXP_H3210, BR[4][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#4 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#4 | AR[3] | */ mop(OP_STWR,ex0, &AR[4][0], oofs, d02[CHIP], MSK_D0, d02w[CHIP], len2, 0, 1, NULL, len2); /* stage#4 | + ST v */ #if (H>3) /* *--------- BR[4] */ exe(OP_CMP_LT, &cc1, l03[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#4 LD */ mop(OP_LDWR, 1, &BR[5][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#1 stage#5 | */ mop(OP_LDWR, 1, &BR[5][0][1], d03[CHIP], oofs, MSK_W0, d03w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#5 +-> | */ mop(OP_LDWR, 1, &BR[5][1][1], d03[CHIP], rofs, MSK_W0, d03w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#5 +-> | */ exe(OP_FMS, &AR[5][0], BR[5][0][1], EXP_H3210, BR[5][1][1], EXP_H3210, BR[5][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#5 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#5 | AR[4] | */ mop(OP_STWR,ex0, &AR[5][0], oofs, d03[CHIP], MSK_D0, d03w[CHIP], len2, 0, 1, NULL, len2); /* stage#5 | + ST v */ #endif #endif #endif } } } //EMAX5A end } /* j-loop */ //EMAX5A drain_dirty_lmm } /* else */ }
  • 5. 20220202 5 逆行列には、ローカルメモリ自己更新 for (j=i+1; j<M; j+=NCHIP*H*RMGRP) { /* 行方向 */ //EMAX5A begin inv_x1 mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { for (INIT1=1,LOOP1=RMGRP,rofs=0-M*4; LOOP1--; INIT1=0) { /* stage#0 *//* mapped to FOR() on BR[63][1][0] */ for (INIT0=1,LOOP0=M-(i+1),cofs=0; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */ exe(OP_ADD, &cofs, INIT0?cofs:cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */ exe(OP_ADD, &rofs, rofs, EXP_H3210, INIT0?M*4:0, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#0 */ exe(OP_ADD, &oofs, rofs, EXP_H3210, cofs, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#1 */ /***************************/ /* + - - - - - - - - - - - */ /* A[p[i]] 先頭行 */ /* 先頭行はi更新まで再利用可能 */ /* | * > > > > > > > > > > */ /* A[p[j]] 次行から引く */ /* 1行をLMMに写像 */ /* | v + - - - - - - - - - */ /* | v | * > > > > > > > > */ /* M/60を収容してi更新までj+=60を繰り返す *//* 行番号比較とcstによる端数制御 */ /* | v | v + - - - - - - - */ /* + CHIP#0 h=0 grp=0 */ /* | v | v - + - - - - - - */ /* + CHIP#0 h=0 grp=1 */ /* | v | v - - + - - - - - */ /* + CHIP#1 h=0 grp=0 */ /* | v | v - - - + - - - - */ /* + CHIP#1 h=0 grp=1 */ /* | v | v - - - - + - - - */ /* + CHIP#0 h=1 grp=0 */ /* | v | v - - - - - + - - */ /* + CHIP#0 h=1 grp=1 */ /* | v | v - - - - - - + - */ /* + CHIP#1 h=1 grp=0 */ /* | v | v - - - - - - - + */ /* + CHIP#1 h=1 grp=1 */ /***************************/ /* 最大60行まで写像可能 */ /* FOLDING時は,少なくとも第0列がFOLDINGであることが必要(conv-c2c仕様) */ /* CEXEにも関わらずSTWRの無意味なLMM入れ換えが発生するため,A[M][*](枠外領域)を使用 */ /* OK exe-loop */ exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#1 LD */ mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#2 | */ mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */ mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#2 +-> | */ exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa); /* stage#2 | AR[1] | */ mop(OP_STWR,ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2); /* stage#2 | + ST v */ #if (H>1) /* *--------- BR[2] */ exe(OP_CMP_LT, &cc1, l01[CHIP], EXP_H3210, M, EXP_H3210, 0LL, EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#2 LD */ mop(OP_LDWR, 1, &BR[3][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[i]*M+k] stage#3 | */ mop(OP_LDWR, 1, &BR[3][0][1], d01[CHIP], oofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */ mop(OP_LDWR, 1, &BR[3][1][1], d01[CHIP], rofs, MSK_W0, d01w[CHIP], len2,0, 1, NULL, len2); /* A[p[j+h*NCHIP+CHIP]*M+k] stage#3 +-> | */ exe(OP_FMS, &AR[3][0], BR[3][0][1], EXP_H3210, BR[3][1][1], EXP_H3210, BR[3][2][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0); /* stage#3 | ■■■ | 1.0 */ cex(OP_CEXE, &ex0, 0, 0, 0, cc1, 0xaaaa); /* stage#3 | AR[2] | */ mop(OP_STWR,ex0, &AR[3][0], oofs, d01[CHIP], MSK_D0, d01w[CHIP], len2, 0, 1, NULL, len2); /* stage#3 | + ST v */ #if (H>2) /* *--------- BR[3] */ if (j+h*NCHIP*RMGRP+CHIP*RMGRP+grp<M) A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i+1+k] -= A[(j+h*NCHIP*RMGRP+CHIP*RMGRP+grp)*M+i]*A[i*M+i+1+k];
  • 6. 20220202 6 条件付きストア機能を使う exe(OP_CMP_LT, &cc0, l00[CHIP], EXP_H3210, M, EXP_H3210, 0LL, mop(OP_LDWR, 1, &BR[2][2][1], top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); mop(OP_LDWR, 1, &BR[2][0][1], d00[CHIP], oofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); mop(OP_LDWR, 1, &BR[2][1][1], d00[CHIP], rofs, MSK_W0, d00w[CHIP], len2,0, 1, NULL, len2); exe(OP_FMS, &AR[2][0], BR[2][0][1], EXP_H3210, BR[2][1][1], EXP_H3210, BR[2][2][1], cex(OP_CEXE, &ex0, 0, 0, 0, cc0, 0xaaaa ); mop(OP_STWR, ex0, &AR[2][0], oofs, d00[CHIP], MSK_D0, d00w[CHIP], len2, 0, 1, NULL, len2); 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
  • 7. 20220202 7 逆行列には、ローカルメモリ自己更新 /* 前進消去 */ for (i=0; i<M; i++) { /* 列方向 */ for (j=0; j<M; j++) /* 行方向 */ b[i*M+j] = (i==j)?1.0:0.0; } for (i=0; i<M; i+=NCHIP*H) { /* 列方向 */ /*for (j=1; j<M; j++) { *//*通常の連立一時方程式の場合*/ for (j=i+1; j<M; j++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでj=i+1から開始 */ Uint *top = &A[j*M+i]; /* A[p[j]*M+k] */ Uint *topw = (Ull)top; /*Uint len = (j+1)/2;*/ Uint len = j-i;/* bが単位行列の場合,k<iではb[]==0なのでk=iから開始 */ /********************************************/ if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */ for (CHIP=0; CHIP<NCHIP; CHIP++) { for (h=0; h<H; h++) { /* vertical (parallel) execution */ /*for (k=0; k<j; k++) { *//*通常の連立一時方程式の場合*/ for (k=i; k<j; k++) { /* 逆行列(b[]=E)の場合,k<iではb[]==0なのでk=iから開始 */ b[(i+CHIP*H+h)*M+j] -= A[j*M+k]*b[(i+CHIP*H+h)*M+k]; } } } } else { Uint jc = j-i; //EMAX5A begin inv_x2 mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { for (INIT0=1,LOOP0=jc,cofs=0-4; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */ exe(OP_ADD, &cofs, cofs, EXP_H3210, 4LL, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */ mop(OP_LDWR, 1, &Ajk, top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[j]*M+k] *//* stage#1.0 */ mop(OP_LDWR, 1, &BR[1][3][1], t000[CHIP], cofs, MSK_W0, t000w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#1.3 +->xxx LD */ mop(OP_LDWR, 1, &b000, d000[CHIP], 0, MSK_W0, d000w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#2.0 | ■■■ | */ exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[1][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#2.0 +- xxx+ST v */ mop(OP_STWR, 1, &b000, 0, d000[CHIP], MSK_D0, d000w[CHIP], 1, 0, 1, NULL, 1); /* stage#2.0 +--------- xxx */ #if (H>1) mop(OP_LDWR, 1, &BR[2][3][1], t010[CHIP], cofs, MSK_W0, t010w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#2.3 +->xxx LD */ mop(OP_LDWR, 1, &b000, d010[CHIP], 0, MSK_W0, d010w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#3.0 | ■■■ | */ exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[2][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#3.0 +- xxx+ST v */ mop(OP_STWR, 1, &b000, 0, d010[CHIP], MSK_D0, d010w[CHIP], 1, 0, 1, NULL, 1); /* stage#3.0 +--------- xxx */ #if (H>2) : #endif #endif } } //EMAX5A end //EMAX5A drain_dirty_lmm } /* else */ /********************************************/ } /* j-loop */ }
  • 8. 20220202 8 逆行列には、ローカルメモリ自己更新 /* 後退代入 */ for (i=0; i<M; i+=NCHIP*H) { /* 列方向 */ for (j=M-1; j>=0; j--) { /* 行方向 */ if (j<M-1) { Uint *top = &A[j*M+j+1]; /* A[p[j]*M+k] */ Uint *topw = (Ull)top; Uint len = M-j-1; /********************************************/ if (len < 16) { /* len<1でも正常なので性能最大化で決めてよい */ for (CHIP=0; CHIP<NCHIP; CHIP++) { for (h=0; h<H; h++) { /* vertical (parallel) execution */ for (k=M-1; k>j; k--) { /* 最内列方向 */ b[(i+CHIP*H+h)*M+j] -= A[j*M+k]*x[(i+CHIP*H+h)*M+k]; } } } } else { Uint jc = M-j-1; //EMAX5A begin inv_x3 mapdist=0 for (CHIP=0; CHIP<NCHIP; CHIP++) { for (INIT0=1,LOOP0=jc,cofs=jc*4; LOOP0--; INIT0=0) { /* stage#0 *//* mapped to FOR() on BR[63][0][0] */ exe(OP_ADD, &cofs, cofs, EXP_H3210, -4, EXP_H3210, 0LL, EXP_H3210, OP_AND, 0x00000000ffffffffLL, OP_NOP, 0LL); /* stage#0 */ mop(OP_LDWR, 1, &Ajk, top, cofs, MSK_W0, topw, len, 0, 0, NULL, len); /* A[p[j]*M+k] *//* */ mop(OP_LDWR, 1, &BR[1][3][1], t000[CHIP], cofs, MSK_W0, t000w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#1.3 +->xxx LD *//*read-modify-w*/ mop(OP_LDWR, 1, &b000, d000[CHIP], 0, MSK_W0, d000w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#2.0 | ■■■ | */ exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[1][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#2.0 +- xxx+ST v */ mop(OP_STWR, 1, &b000, 0, d000[CHIP], MSK_D0, d000w[CHIP], 1, 0, 1, NULL, 1); /* stage#2.0 +--------- xxx */ #if (H>1) mop(OP_LDWR, 1, &BR[2][3][1], t010[CHIP], cofs, MSK_W0, t010w[CHIP], len, 0, 1, NULL, len); /* b[(i+CHIP*W*H+h*W+0)*M+k] *//* stage#2.3 +->xxx LD *//*read-modify-w*/ mop(OP_LDWR, 1, &b000, d010[CHIP], 0, MSK_W0, d010w[CHIP], 1, 0, 1, NULL, 1); /* b[(i+CHIP*W*H+h*W+0)*M+j] *//* stage#3.0 | ■■■ | */ exe(OP_FMS, &b000, b000, EXP_H3210, Ajk, EXP_H3210, BR[2][3][1], EXP_H3210, OP_NOP, 0LL, OP_NOP, 0LL); /* stage#3.0 +- xxx+ST v */ mop(OP_STWR, 1, &b000, 0, d010[CHIP], MSK_D0, d010w[CHIP], 1, 0, 1, NULL, 1); /* stage#3.0 +--------- xxx */ #if (H>2) : #endif #endif } } //EMAX5A end //EMAX5A drain_dirty_lmm } /* else */ /********************************************/ } /* if (j<M-1) */ for (CHIP=0; CHIP<NCHIP; CHIP++) { for (h=0; h<H; h++) { /* vertical (parallel) execution */ inv1[j*M+p[i+CHIP*H+h]] = x[(i+CHIP*H+h)*M+j] = A[j*M+j]*b[(i+CHIP*H+h)*M+j]; /* PIOにてLMMのx[i*M+j]を直接更新 *//* iはそのままで,jを切替え */ } } } /* j-loop */ }

Notas do Editor

  1. 様々なアプリケーションを取りあげて、アイマックスのポテンシャルを説明するシリーズです。第7回は、逆行列です。
  2. みなさんは、Axイコールbを解いて、xを求める、連立一次方程式の解法を知っていますね。 bの列数を増やして単位行列にすれば、Xの列数が増えて逆行列が求まります。 LU分解を使って、連立一次方程式を解けるので、このアルゴリズムを列方向に拡張すればOKです。
  3. このCプログラムは、左でLU分解し、右で逆行列を求めています。連立一次方程式のコードが、青字のコメントに残してあります。修正後の赤字が、逆行列のコードです。これをアイマックスに書き換えていきます。
  4. 逆行列計算をアイマックスに書き換える際に、注意すべき点があります。これまでのプログラムは、データの横方向の長さが一定でした。しかし、LU分解を使うということは、三角行列を扱います。これは、横方向のデータの長さが、徐々に長くなったり、短くなったりすることを意味します。たとえば、横方向の長さが1ワードしかない場合、CPUで実行したほうが速いので、最初から最後まで、全部アイマックスに計算させるのは愚かです。そこで、このプログラムのように、まず、データ長を調べて、短い場合は、左のCPUのコード、長い場合は、右のアイマックスのコードを使うといった、工夫をします。前に言ったように、アイマックスのコードは、CPUでも動かすことができるので、このような、ハイブリッドプログラムのデバッグも難しくありません。
  5. 右側の一部を拡大しました。赤枠の中が、元のCPUコードです。条件文の中に、メモリのあたいを更新する計算が書いてあります。これに対応するアイマックスのコードが、下の赤字部分です。機械学習編の中で、普通のCGRAは、行列積を縦に計算しますが、アイマックスは、縦にも横にも計算できると言いました。後者は、ローカルメモリの内容を取り出して、加工し、書き戻す時に役立ちます。この赤字部分も、後者を利用して実装しています。赤字部分は、逆行列計算の1行分に対応し、同様の組を下にコピーすることで、複数ぎょうの処理を一度に行います。
  6. さらに拡大しました。条件文に相当する機能は、画像フィルタ上級編で説明しました。条件付き代入機能CMOVが、データを切り替えることができました。しかし、今回は、ストアするかどうかを切り替える必要があります。このためにアイマックスが備えているのが、条件付きストアです。まず、最初のぎょうの、CMP関数が、上位32ビット同士の比較結果と、下位32ビット同士の比較結果を、64ビットレジスタの、ビット32とビット0に格納します。次に、CEX関数が用意されています。3番目から6番目のパラメタに、CMP関数の結果を指定します。使わない部分は0にします。CEX関数は、4つのパラメタで指定された64ビットレジスタの、ビット32だけを並べて4ビットのあたいにし、7番目の16ビットパラメタと組み合わせて、ex0のうえ1ビットを生成します。同じように、4つのビット0を並べて4ビットのあたいにしたものから、ex0のした1ビットを生成します。あとは、4ビットの比較結果と、16ビットパラメタから、どうやってex0の1ビットを作るかを理解すればおわりです。下の図をみてください。4ビットの比較結果は、0000からいちいちいちいちまでの16通りあります。0000の場合にストアするかどうかを、16ビットパラメタのビット0に指定します。同様に、0001の場合にストアするかどうかを、16ビットパラメタのビット1に指定します。 こうして生成した、ex0を使って、最後のストアを制御します。今までと違って、最後のストア関数の2番目に、ex0というパラメタが増えています。うえ1ビットが、ストアデータの上位32ビットを本当にストアするかどうか、同様に、下1ビットが、下位32ビットをストアするかどうかを決めます。もうわかりましたね。複数のCMP関数で作った、合計4ビットの比較結果を使って、あらゆるパターンの条件付きストアを、上位32ビットと下位32ビット独立に、書くことができます。赤字の部分では、ビット0しか使っていないので、比較結果は、0000か0001の2通りしかありません。16ビットパラメタに、ここでは、aaaaと書いてありますが、0002でも同じ意味です。
  7. LU分解が終わったので、次は、前進消去です。こまかい説明は省略です。
  8. 最後の、後退代入です。
  9. 3つまとめて、コンパイル結果です。黒い部分が多いので、まだ高密度化できそうです。これは、みなさんへの宿題です。
  10. 今回は、逆行列を題材に、ローカルメモリ更新機能や、条件付きストアを説明しました。では、今回はここまでです。おつかれさま。