キャッシュにヒットし続けるようにループを分割してみた(簡単のため配列の使い方も少し変えてる).3倍から5倍程度速くなった.あとは sse2 の命令とか使ってみたいところだけどうまく使える形にプログラムを変形できない… むりかなぁ?
初期の単純なネストループ:
for(int p = R; p >0; p--) { int q = (ISROOT()) ? p-1: 0; double *u = U+q; double *v = u++; register double cv = *v; for(double const *e = U+Len+p; u != e; u++,v++){ register const double cu = *u; *v = (1 - MU) * cu + MU * cv; cv = cu; } }
内側のループを分割してキャッシュ上のデータにアクセスしまくる:
double *uu = U; for(int p = R; p >0; p--) { int q = (ISROOT()) ? p-1: 0; double *u = uu+q; double *v = u++; register double cv = *v; for(double const *e = uu+p; u != e; u++,v++){ register const double cu = *u; *v = (1 - MU) * cu + MU * cv; cv = cu; } } double const *uue = uu + Len - STEPLEN; // iteration - STEPLEN * floor(Len/STEPLEN) steps for(; uu < uue; uu+=STEPLEN) { for(int p = R; p >0; p--) { double *u = uu+p-1; double *v = u++; register double cv = *v; for(double const *e = uu+STEPLEN+p; u != e; u++,v++){ register const double cu = *u; *v = (1 - MU) * cu + MU * cv; cv = cu; } } } // last - rest steps int rlen = Len - STEPLEN * (Len/STEPLEN); for(int p = R; p >0; p--) { double *u = uu+p-1; double *v = u++; register double cv = *v; for(double const *e = uu+rlen+p; u != e; u++,v++){ register const double cu = *u; *v = (1 - MU) * cu + MU * cv; cv = cu; } }
- Newer: AWK - はじめ