• 検索結果がありません。

キャッシュの利用

ドキュメント内 橡3sec3.PDF (ページ 56-61)

STS MACL,R2 MOV.L R2,@R5 ADD #4,R5 MOV.L @R4+,R2 MOV.L @R6+,R1 MUL.L R2,R1 STS MACL,R2 MOV.L R2,@R5 ADD #4,R5 MOV.L @R4+,R2 MOV.L @R6+,R1 MUL.L R2,R1 STS MACL,R2 MOV.L R2,@R5 ADD #4,R5 MOV.L @R4+,R2 MOV.L @R6+,R1 MUL.L R2,R1 STS MACL,R2 MOV.L R2,@R5 BF/S L242 ADD #4,R5 RTS

LDS.L @R15+,MACL L243:

.DATA.W H'04B0 .DATA.L _a .DATA.L _b .DATA.L _c

MOV.L @R5+,R1 MUL.L R3,R1 STS MACL,R3 MOV.L R3,@R6 MOV.L @R4+,R3 ADD #4,R6 MOV.L @R5+,R1 MOV R4,R2 MUL.L R3,R1 ADD #32,R2 STS MACL,R3 MOV.L R3,@R6 ADD #4,R6 PREF @R2 MOV.L @R4+,R2 ADD #4,R7 MOV.L @R5+,R1 CMP/GE R0,R7 MUL.L R2,R1 STS MACL,R2 MOV.L R2,@R6 ADD #4,R6 MOV.L @R4+,R2 MOV.L @R5+,R1 MUL.L R2,R1 STS MACL,R2 MOV.L R2,@R6 BF/S L242 ADD #4,R6 RTS

LDS.L @R15+,MACL L243:

.DATA.W H’04B0 .DATA.L _a .DATA.L _b .DATA.L _c

■改善前後のコードサイズと実行速度

改善前 改善後1

(PREF1のみ)

改善後2

(PREF1,2)

コードサイズ 84byte 92byte 96byte

実行速度 91,327cycle 89,526cycle 84,696cycle

【注】測定条件はcpu=sh3に設定し、プログラムを外部メモリへロードし、外部メモリ へのアクセスサイクル数を16にて測定した。

3.9.2 タイリング

■ポイント

データアクセスに局所性を持たせてデータキャッシュミスを少なくすようなプログラミングを 行います。

言い換えれば、キャッシュがヒットしている状態で計算できるものは、先にしてしまうテクニ ックです。

■説明

   簡単な例として、二つの配列、A、B に対する差分の総和をとる配列を作成する例を示します。

   そこで、アクセスの順番を変えてプログラミングすることによって、データキャッシュミスを  削減するようなプログラミングをします。

■使用例

構造体は配列のメンバ、a,b,c,dに対し、

di=Σj bj-aj の計算を行う。

改善前ソースコード typedef struct { float a,b,c,d;

} data_t;

f(data_t data[], int n) {

data_t *p,*q;

data_t *p_end = &data[n];

data_t *q_end = p_end;

float a,d;

for (p = data; p < p_end; p++){

a = p->a;

d = 0.0f;

for (q = data; q < q_end; q++){

d += q->b -a;

} p->d=d;

} }

改善後ソースコード

#define STRIDE 512 typedef struct { float a,b,c,d;

} data_t;

f(data_t data[], int n) {

data_t *p,*q, *end=&data[n];

data_t *pp, *qq;

data_t *pp_end, *qq_end;

float a,d;

for (p = data; p < end; p = pp_end){

pp_end = p + STRIDE;

for (q = data; q < end; q = qq_end){

qq_end = q + STRIDE;

for (pp = p; pp < pp_end && pp

<end; pp++){

a = pp->a;

d = pp->d;

for (qq = q; qq < qq_end

&& qq < end; qq++){

d += qq->b -a;

}

p->d = d;

} } }

}改善後アセンブリ展開コード

MOV R4,R6 L245:

MOV R4,R5 FMOV.S @R6,FR5 CMP/HS R1,R5 BT/S L246 FMOV.S FR6,FR4 L247:

STS FPSCR,R3 MOV.L L248,R2 MOV #4,R0

FMOV.S @(R0,R5),FR3 ADD #16,R5 AND R2,R3 CMP/HS R1,R5 LDS R3,FPSCR FSUB FR5,FR3 BF/S L247 FADD FR3,FR4 L246:

MOV #12,R0 FMOV.S FR4,@(R0,R6) ADD #16,R6 L244:

CMP/HS R1,R6 BF L245 RTS

NOP L248:

.DATA.L H'FFE7FFFF .END

ADD R4,R7 MOV.W L259,R11 BRA L249 MOV R4,R13 L250:

MOV R13,R10 ADD R11,R10 BRA L251 MOV R4,R14 L252:

MOV R14,R1 ADD R11,R1 BRA L253 MOV R13,R6 L254:

MOV #12,R0 FMOV.S @R6,FR5 FMOV.S @(R0,R6),FR4 BRA L255

MOV R14,R5 L256:

STS FPSCR,R3 MOV.L L259+2,R2 MOV #4,R0

FMOV.S @(R0,R5),FR3 ADD #16,R5 AND R2,R3 LDS R3,FPSCR FSUB FR5,FR3 FADD FR3,FR4 L255:

CMP/HS R1,R5 BT L257 CMP/HS R7,R5 BF L256

L257:

MOV #12,R0 ADD #16,R6

FMOV.S FR4,@(R0,R13) L253:

CMP/HS R10,R6 BT L258 CMP/HS R7,R6 BF L254

L258:

MOV R1,R14 L251:

CMP/HS R7,R14 BF L252 MOV R10,R13 L249:

CMP/HS R7,R13 BF L250 MOV.L @R15+,R10 MOV.L @R15+,R11 MOV.L @R15+,R13 RTS

MOV.L @R15+,R14 L259:

.DATA.W H'2000 .DATA.L H'FFE7FFFF .END

■ 改善前後のコードサイズと実行速度 (SH-4)

改善前 改善後

コードサイズ 52byte 104byte 実行速度 1,486×106cycle 1,068×106cycle 【注】n=8192、STRIDE=512の場合

■改善前後のプログラム解説

改善前と後では、改善後の方がループが4重になった為、処理が複雑になり、コードサイズ

も大きくなります。ただし、このような処理をすることで、キャッシュミスによるオーバヘッド を削減することが可能です。よって、処理するデータが小さな場合には効果はありませんが、デ ータが大きい場合に効果があります。

改善前では、一つのデータdata[0]->dを求めるために、data[0]~data[n-1]までを順次参照します。

次に、data[1]->dを求めるために、再度、data[0]~data[n-1]を参照しようとしますが、配列dataの サイズが、キャッシュのサイズに比べ大きいときには、既に、data[0]の内容はキャッシュにはな くなっており、キャッシュミスを起こします。

大きな領域を順次参照していくため、同じデータの次の参照まで、キャッシュ中にデータが残 っていないことになります。

改善後のプログラムでは、小さな区間に分割してデータをアクセスするため、そのデータアク セスの間のキャッシュミスは少なくなります。計算の順番を換えて、キャッシュがヒットしてい る間に、別の計算もしてしまう手法です。

ドキュメント内 橡3sec3.PDF (ページ 56-61)

関連したドキュメント