I3CPAC+Exercise+10

toc =Exercise 10: Cache= //Øvelsen er at skrive et lille program som laver en matrix multiplikation. Der eksperimenteres med forskellige kompilerings-parametre i GCC, og ekseveringstiden på target noteres og sammenlignes//

Først forsøgte vi med matricer på 100x100, men da dette gav temmeligt hurtige eksekveringstider for selv uoptimeret kode og kompilering, bruger vi matricer på 500x500.

Ikke optimeret kode
//I denne sektion afprøves kode som ikke er optimeret til sekventiel læsning fra cachen.//

code format="cpp" for (i = 0; i < N; ++i) for (j = 0; j < N; ++j) for (k = 0; k < N; ++k) res[i][j] += mul1[i][k] * mul2[k][j];

code Tabel over ekseveringstider med forskellige kompileringsparametre
 * <  ||< real ||< user ||< sys ||
 * < O0 ||< 53.81s ||< 53.60s ||< 0.07s ||
 * < O1 ||< 34.04s ||< 33.86s ||< 0.10s ||
 * < O2 ||< 34.12s ||< 34.04s ||< 0.06s ||
 * < O3 ||< 34.13s ||< 34.04s ||< 0.07s ||

Optimeret kode
//I denne sektion er koden forsøgt optimeret til sekventiel læsning fra cachen, ved at transponere den ene af matricerne inden multiplikationen udføres. Dette medfører at der kommer færre 'misses' i cachen, som dermed ikke skal indlæse nye instruktioner så ofte//

code format="cpp"

for (i = 0; i < N; ++i) for (j = 0; j < N; ++j) tmp[i][j] = mul2[j][i]; for (i = 0; i < N; ++i) for (j = 0; j < N; ++j) for (k = 0; k < N; ++k) res[i][j] += mul1[i][k] * tmp[j][k];

code

Tabel over ekseveringstider med forskellige kompileringsparametre


 * <  ||< real ||< user ||< sys ||
 * < O0 ||< 40.26s ||< 40.16s ||< 0.05s ||
 * < O1 ||< 20.47s ||< 20.42s ||< 0.04s ||
 * < O2 ||< 20.86s ||< 20.76s ||< 0.08s ||
 * < O3 ||< 20.86s ||< 20.78s ||< 0.07s ||

Konklusion
Udfra ovenstående kan det observeres at der er væsentlige forbedringer i eksekveringstiden, både ved hensigtsmæssig kode, og ved kompileroptimering. Kompileroptimering "O2" og "O3" gav ikke nogen mærkbar forbedring sammenlignet med "O1". Dette kan skyldes, at disse optimerer på flag eller parametetre som ikke bliver benyttet i vores kode.