Departemen Teknik Elektro Institut Teknologi Bandung 2005
EC3003 - Sistem Komputer
Bagian 10
Pembahasan
Organisasi cache memory
Direct mapped cache
Set associative cache
Cache Memory
Cache memory adalah memori berbasis SRAM berukuran kecil dan berkecepatan tinggi yang dikendalikan secara otomatis oleh
hardware.
Menyimpan suatu blok dari main memory yang sering diakses oleh CPU
Dalam operasinya, pertama-tama CPU akan mencari data di L1, kemudian di L2, dan main memory.
main memory I/O bridge bus interface L2 cache ALU register file CPU
cache bus system bus memory bus
L1 cache
L1 Cache
a b c d blok 10 p q r s...
...
blok 21 w x y z...
blok 30main memory memiliki tempat untuk meyimpan blok-blok
berukuran 4-word
L1 cache memiliki tempat untuk menyimpan dua blok berukuran 4-word
register dalam CPU memiliki tempat untuk menyimpan empat word berukuran 4-byte.
Satuan transfer antara cache dan main memory dalam blok berukuran 4-word
Satuan transfer antara register dan cache dalam blok berukuran 4-byte
baris 0 baris 1
Organisasi Cache Memory
• • • B–1 1 0 • • • B–1 1 0 valid valid tag tag set 0: B = 2b byteper blok cache
E baris per set S = 2s set t tag bit per baris 1 valid bit per baris Ukuran cache : C = B x E x S byte data • • • • • • B–1 1 0 • • • B–1 1 0 valid valid tag tag • • • set 1: • • • B–1 1 0 • • • B–1 1 0 valid valid tag tag set S-1: • • • • • •
Cache adalah array dari kumpulan set.
Setiap set berisi satu atau lebih baris.
Setiap baris
menyimpan satu blok data.
Pengalamatan Cache
t bit s bit b bit
0 m-1
<tag> <set index> <block offset> Alamat A: • • • B–1 1 0 • • • B–1 1 0 v v tag tag • • • set 0: • • • B–1 1 0 • • • B–1 1 0 v v tag tag • • • set 1: • • • B–1 1 0 • • • B–1 1 0 v v tag tag • • • • • • set S-1:
Data word pada alamat A berada dalam cache jika bit <tag> dan <set index> cocok dan berada dalam baris yang valid.
Isi word dimulai dari byte ofset <block offset> pada awal blok
Direct-Mapped Cache
Cache yang sederhana
Setiap set hanya memiliki satu baris (line)
valid valid valid tag tag tag set S-1: • • • set 0: set 1:
E=1 baris per set
blok cache blok cache
Mengakses Direct-Mapped Cache
Memilih set
Menggunakan bit set index untuk memilih set yang digunakan
valid valid valid tag tag tag set S-1: t bit s bit • • • set 0: set 1: 0 0 0 0 1 0 b bit tag set index block offset
m-1
set dipilih
blok cache blok cache
Mengakses Direct-Mapped Cache
Pencocokan baris dan pemilihan word
Pencocokan baris : mencari baris valid dalam set yang dipilih
dengan mencocokan tag
Pemilihan word : Selanjutnya mengekstraksi word
1 t bit s bit 100 i 0110 0 b bit tag set index block offset Set dipilih (i):
m-1
(3) Jika (1) dan (2), maka cache hit, dan block offset memilih posisi awal byte
=1? (1) Bit valid harus di-set
= ? (2) Bit tag pada cache
harus cocok dengan bit tag pada alamat
0110 w0 w1 w2 w3
3
Simulasi Direct-Mapped Cache
M=16 byte alamat, B=2 byte/blok, S=4 set, E=1 entri/set
Penelusuran alamat (baca):
0 [00002], 1 [00012], 13 [11012], 8 [10002], 0 [00002] x t=1 s=2 b=1 xx x 1 0 m[1] m[0] v tag data 0 [00002] (miss) (1) 1 0 m[1] m[0] v tag data 1 1 m[13] m[12] 13 [11012] (miss) (3) 1 1 m[9] m[8] v tag data 8 [10002] (miss) (4) 1 0 m[1] m[0] v tag data 1 1 m[13] m[12] 0 [00002] (miss) (5) 0 M[0-1] 1 1 M[12-13] 1 1 M[8-9] 1 1 M[12-13] 1 0 M[0-1] 1 1 M[12-13] 1 0 M[0-1] 1
Bit Tengah Sebagai Indeks
Bit indeks orde tinggi
Baris memori yang bersebelahan akan dipetakan pada lokasi cache sama
Spatial locality yang buruk
Bit indeks orde tengah
Baris memori yang berurutan
dipetakan pada baris cache berbeda
Dapat menyimpan urutan byte
pada cache dalam satu waktu
4-baris cache Bit atas Bit tengah
00 01 10 11 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Set Associative Cache
Setiap set memiliki lebih dari satu baris
valid tag
set 0: E=2 baris per set
set 1:
set S-1:
• • •
blok cache
valid tag blok cache
valid tag blok cache
valid tag blok cache
valid tag blok cache
Mengakses Set Associative Cache
Memilih set
Serupa dengan direct-mapped cache
valid valid tag tag set 0: valid valid tag tag set 1: valid valid tag tag • • • set S-1: t bit s bit 0 0 0 0 1 0 b bit tag set index block offset
m-1 Set dipilih blok cache blok cache blok cache blok cache blok cache blok cache
Mengakses Set Associative Cache
Pencocokan baris dan pemilihan word
Harus membandingkan setiap tag pada baris yang valid dalam
set yang dipilih
1 0110 w0 w1 w2 w3 1 1001 t bit s bit 100 i 0110 0 b bit tag set index block offset Set dipilih (i):
=1?
m-1
(1) Bit valid harus di-set.
= ? (2) Bit tag pada salah satu
baris cache harus cocok dengan bit tag pada alamat
(3) Jika (1) dan (2), maka cache hit, dan block offset memilih posisi awal byte
3
Multi-Level Cache
Pada cache, data dan instruksi dapat dipisah atau diletakkan dalam tempat yang sama
Ukuran : Kecepatan : $/Mbyte: Baris: 200 B 3 ns 8 B 8-64 KB 3 ns 32 B 128 MB DRAM 60 ns $1.50/MB 8 KB 30 GB 8 ms $0.05/MB
Bertambah besar, lambat dan murah
Memori Memori L1 d-cache Reg Unified L2 Cache Unified L2 Cache Prosesor 1-4MB SRAM 6 ns $100/MB 32 B L1 i-cache disk disk
Hirarki Cache Intel Pentium
Chip Prosesor Chip Prosesor L1 Data 1 cycle latency 16 KB 4-way assoc Write-through 32B lines L1 Instruction 16 KB, 4-way 32B lines Reg. L2 Unified 128KB--2 MB 4-way assoc Write-back Write allocate 32B lines L2 Unified 128KB--2 MB 4-way assoc Write-back Write allocate 32B lines Main Memory Hingga 4GB Main Memory Hingga 4GBMetrik Kinerja Cache
Miss Rate
Persentase referensi memori yang tidak ditemukan dalam cache
(miss/referensi).
Umumnya 3-10% untuk L1, < 1% untuk L2.
Hit Time
Waktu untuk mengirimkan data dari cache ke prosesor
(termasuk waktu untuk menentukan apakah data tersebut terdapat dalam cache).
Umumnya 1 siklus clock untuk L1, 3-8 siklus clock untuk L2.
Miss Penalty
Waktu tambahan yang diperlukan karena terjadi miss
Menulis Kode yg Cache Friendly
Kode yang baik :
Melakukan referensi berulang-ulang terhadap suatu variabel
(temporal locality)
Pola referensi stride-1 (spatial locality)
Contoh : cold cache, 4-byte words, 4-word cache blocks
int sumarrayrows(int a[M][N]) { int i, j, sum = 0; for (i = 0; i < M; i++) for (j = 0; j < N; j++) sum += a[i][j]; return sum; }
int sumarraycols(int a[M][N]) { int i, j, sum = 0; for (j = 0; j < N; j++) for (i = 0; i < M; i++) sum += a[i][j]; return sum; }
Gunung Memori
Membaca throughput (membaca bandwidth)
Banyaknya byte yang terbaca dari memori setiap
detik (MB/detik)
Gunung memori
Ukuran throughput sebagai fungsi dari spatial locality
dan temporal locality.
Fungsi Tes Gunung Memori
/* The test function */
void test(int elems, int stride) { int i, result = 0;
volatile int sink;
for (i = 0; i < elems; i += stride) result += data[i];
sink = result; /* So compiler doesn't optimize away the loop */ }
/* Run test(elems, stride) and return read throughput (MB/s) */ double run(int size, int stride, double Mhz)
{
double cycles;
int elems = size / sizeof(int);
test(elems, stride); /* warm up the cache */
cycles = fcyc2(test, elems, stride, 0); /* call test(elems,stride) */ return (size / stride) / (cycles / Mhz); /* convert cycles to MB/s */ }
Rutin Utama Gunung Memori
/* mountain.c - Generate the memory mountain. */
#define MINBYTES (1 << 10) /* Working set size ranges from 1 KB */ #define MAXBYTES (1 << 23) /* ... up to 8 MB */
#define MAXSTRIDE 16 /* Strides range from 1 to 16 */ #define MAXELEMS MAXBYTES/sizeof(int)
int data[MAXELEMS]; /* The array we'll be traversing */ int main()
{
int size; /* Working set size (in bytes) */ int stride; /* Stride (in array elements) */ double Mhz; /* Clock frequency */
init_data(data, MAXELEMS); /* Initialize each element in data to 1 */ Mhz = mhz(0); /* Estimate the clock frequency */
for (size = MAXBYTES; size >= MINBYTES; size >>= 1) { for (stride = 1; stride <= MAXSTRIDE; stride++)
printf("%.1f\t", run(size, stride, Mhz)); printf("\n");
}
exit(0); }
Gunung Memori
s1 s3 s5 s7 s9 s1 1 s1 3 s15 8m 2m 51 2k 128k 32 k 8k 2k 0 200 400 600 800 1000 1200 re a d t h rou ghp ut ( M B /s )stride (words) working set size (bytes)
Pentium III Xeon 550 MHz 16 KB on-chip L1 d-cache 16 KB on-chip L1 i-cache 512 KB off-chip unified L2 cache Punggung gunung memperlihatkan Temporal Locality L1 L2 mem Kemiringan untuk Spatial Locality xe
Punggung Gunung - Temporal
Potongan gunung memori dengan stride=1
Memperlihatkan throughput dari cache dan memori berbeda.
0 200 400 600 800 1000 1200 8m 4m 2m 1024 k 512 k 256 k 128 k 64 k 32 k 16 k 8k 4k 2k 1k
working set size (bytes)
re a d thr o ug p u t (M B /s ) L1 cache region L2 cache region main memory region
Kemiringan – Spatial Locality
Potongan pada gunung memori dengan ukuran 256 KB.
Memperlihatkan ukuran blok cache
0 100 200 300 400 500 600 700 800 s1 s2 s3 s4 s5 s6 s7 s8 s9 s10 s11 s12 s13 s14 s15 s16 re ad t hr o ugh put (M B /s)
Contoh Perkalian Matriks
Pengaruh utama cache yang penting :
Total ukuran cache
Memperlihatkan temporal locality, tetap mempertahankan working set tetap
kecil (contoh : dengan menggunakan blocking)
Ukuran blok
Memperlihatkan spatial locality
Deskripsi :
Perkalian matriks NxN Total operasi O(N3) Akses
N pembacaan untuk setiap elemen sumber
N nilai dijumlahkan untuk setiap tujuan
Dapat disimpan di register
/* ijk */
for (i=0; i<n; i++) { for (j=0; j<n; j++) { sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum; } } /* ijk */
for (i=0; i<n; i++) { for (j=0; j<n; j++) { sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum; } }
Analisis Miss Rate
Analisis miss rate pada perkalian matriks
Asumsi :
Ukuran baris = 32B (cukup besar untuk 4 buah 64-bit word) Dimensi matriks (N) sangat besar
Aproksimasi 1/N sama dengan 0.0
Cache tidak terlalu besar untuk menyimpan beberapa baris.
Metoda analisis :
Melihat pola akses pada loop bagian dalam.
C A k i B k j i j
Layout Array C dalam Memori
Array C dialokasikan dalam urutan row-major
Setiap baris (row) terletak dalam memori yang berurutan
Berpindah antar kolom dalam satu baris :
for (i = 0; i < N; i++) sum += a[0][i];
Mengakses elemen yang berurutan
Jika ukuran blok (B) > 4 bytes, eksploit spatial locality
miss rate = 4 bytes / B
Berpindah antar baris dalam satu kolom :
for (i = 0; i < n; i++)sum += a[i][0];
Mengakses elemen yang jauh Tidak terjadi spatial locality!
Perkalian Matriks ijk
/* ijk */
for (i=0; i<n; i++) { for (j=0; j<n; j++) { sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum; } } /* ijk */
for (i=0; i<n; i++) { for (j=0; j<n; j++) { sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum; } } A B C (i,*) (*,j) (i,j) Loop bagian dalam :
Kolom
Baris Tetap
Miss pada setiap iterasi loop bagian dalam :
A B C
Perkalian Matriks jik
/* jik */
for (j=0; j<n; j++) { for (i=0; i<n; i++) {
sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum } } /* jik */ for (j=0; j<n; j++) { for (i=0; i<n; i++) {
sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum } } A B C (i,*) (*,j) (i,j) Loop bagian dalam :
Baris Kolom Tetap Miss pada setiap iterasi loop bagian dalam :
A B C
Perkalian Matriks kij
/* kij */
for (k=0; k<n; k++) { for (i=0; i<n; i++) {
r = a[i][k]; for (j=0; j<n; j++) c[i][j] += r * b[k][j]; } } /* kij */ for (k=0; k<n; k++) { for (i=0; i<n; i++) {
r = a[i][k]; for (j=0; j<n; j++) c[i][j] += r * b[k][j]; } } A B C (i,*) (i,k) (k,*)
Loop bagian dalam :
Baris Kolom Tetap
Miss pada setiap iterasi loop bagian dalam :
A B C
Perkalian Matriks ikj
/* ikj */
for (i=0; i<n; i++) { for (k=0; k<n; k++) { r = a[i][k]; for (j=0; j<n; j++) c[i][j] += r * b[k][j]; } } /* ikj */
for (i=0; i<n; i++) { for (k=0; k<n; k++) { r = a[i][k]; for (j=0; j<n; j++) c[i][j] += r * b[k][j]; } } A B C (i,*) (i,k) (k,*)
Loop bagian dalam :
Baris Baris Tetap
Miss pada setiap iterasi loop bagian dalam :
A B C
Perkalian Matriks jki
/* jki */
for (j=0; j<n; j++) { for (k=0; k<n; k++) {
r = b[k][j];
for (i=0; i<n; i++)
c[i][j] += a[i][k] * r; } } /* jki */ for (j=0; j<n; j++) { for (k=0; k<n; k++) { r = b[k][j];
for (i=0; i<n; i++)
c[i][j] += a[i][k] * r; } } A B C (*,j) (k,j)
Loop bagian dalam : (*,k)
Kolom Tetap Kolom
Miss pada setiap iterasi loop bagian dalam :
A B C
Perkalian Matriks kji
/* kji */
for (k=0; k<n; k++) { for (j=0; j<n; j++) {
r = b[k][j];
for (i=0; i<n; i++)
c[i][j] += a[i][k] * r; } } /* kji */ for (k=0; k<n; k++) { for (j=0; j<n; j++) { r = b[k][j];
for (i=0; i<n; i++)
c[i][j] += a[i][k] * r; } } A B C (*,j) (k,j)
Loop bagian dalam : (*,k)
Tetap
Kolom Kolom
Miss pada setiap iterasi loop bagian dalam :
A B C
Ringkasan Perkalian Matriks
for (i=0; i<n; i++) { for (j=0; j<n; j++) { sum = 0.0; for (k=0; k<n; k++) sum += a[i][k] * b[k][j]; c[i][j] = sum; } }
ijk (& jik):
• 2 load, 0 store
• miss/iterasi = 1.25
for (k=0; k<n; k++) { for (i=0; i<n; i++) {
r = a[i][k]; for (j=0; j<n; j++) c[i][j] += r * b[k][j]; } } for (j=0; j<n; j++) { for (k=0; k<n; k++) { r = b[k][j];
for (i=0; i<n; i++) c[i][j] += a[i][k] * r; }
}
kij (& ikj):
• 2 load, 1 store • miss/iterasi = 0.5
jki (& kji):
• 2 load, 1 store • miss/iterasi = 2.0
Kinerja Perkalian Matriks Pentium
Miss rate bukan selalu perkiraan yang baik Penjadwalan kode juga berpengaruh
0 10 20 30 40 50 60 25 50 75 100 125 150 175 200 225 250 275 300 325 350 375 400 Array size (n) C y cl es/ it erat io n kji jki kij ikj jik ijk
Meningkatkan Temporal Locality
Meningkatkan temporal locality dengan blocking.Contoh : perkalian matriks dengan blocking
“blok” (di sini) bukan berarti “blok cache blok”. Tetapi berarti suatu sub-blok dalam matriks. Contoh : N = 8; ukuran sub-blok = 4
A11 A12 A21 A22 C11 = A11B11 + A12B21 C12 = A11B12 + A12B22 C21 = A21B11 + A22B21 C22 = A21B12 + A22B22 B11 B12 B21 B22 X = C11 C12 C21 C22
Perkalian Matriks dengan Blok
for (jj=0; jj<n; jj+=bsize) { for (i=0; i<n; i++)
for (j=jj; j < min(jj+bsize,n); j++) c[i][j] = 0.0;
for (kk=0; kk<n; kk+=bsize) { for (i=0; i<n; i++) {
for (j=jj; j < min(jj+bsize,n); j++) { sum = 0.0 for (k=kk; k < min(kk+bsize,n); k++) { sum += a[i][k] * b[k][j]; } c[i][j] += sum; } } } }
Analisis Perkalian Matriks Blok
Pasangan loop paling dalam mengalikan potongan A 1 x bsize dengan blok B
bsize x bsize dan mengakumulasikan menjadi C 1 x bsize.
Loop dengan j langkah melalui potongan A dan C n baris, memakai B sama.
A B C
Potongan baris diakses update potongan elemen berurutan
i kk i
kk jj jj
for (i=0; i<n; i++) {
for (j=jj; j < min(jj+bsize,n); j++) { sum = 0.0 for (k=kk; k < min(kk+bsize,n); k++) { sum += a[i][k] * b[k][j]; } c[i][j] += sum; } Innermost Loop Pair
Kinerja Blocking pada Pentium
Kinerja perkalian matriks dengan blocking pada Pentium
Blocking (bijk and bikj) meningkatkan kinerja dengan faktor dua kali di atas versi unblocked (ijk and jik)
Relatif tidak sensitive terhadap ukuran array.
0 10 20 30 40 50 60 25 50 75 100 125 150 175 200 225 250 275 300 325 350 375 400 Array size (n) Cy cl e s /ite ra tion kji jki kij ikj jik ijk bijk (bsize = 25) bikj (bsize = 25)
Kesimpulan
Pemrogram dalam melakukan optimisasi kinerja cache
Bagaimana struktur data dikelola Bagaimana data diakses
Struktur nested loop
Blocking merupakan teknik umum
Seluruh sistem menyukai “cache friendly code”
Memperoleh kinerja optimum absolut sangat tergantung pada
platform yang digunakan.
Ukuran cache, ukuran line, associativities, dll.
Keuntungan paling besar dapat diperoleh dengan kode generik
Tetap bekerja dalam working set yang kecil (temporal locality) Gunakan stride yang kecil (spatial locality)