A CPU has a 32 KB direct mapped cache with 128 byte block size. Suppose A is a two dimensional array of size 512 x 512 with elements that occupy 8 bytes each. Consider the following two code segments P1 and P2: P1: for (i=0; i<512; i++) { for (j=0; j<512; j++) { x += A[i][j]; } } P2: for (j=0; j<512; j++) { for (i=0; i<512; i++) { x += A[i][j]; } } P1 and P2 are executed independently with the same initial state, namely A is not in the cache and i, j are in registers. Let the number of cache misses experienced by P1 be M1 and that by P2 be M2. The value of M1/M2 is: A. 0 B. 1/16 C. 1/4 D. 16
GATE 2006 · Computer Organization and Architecture · Cache Memory · medium
Answer: M1/M2 = 1/16. Answer: B. 1/16
- Compute M1 for P1 (row-major access): P1 iterates over A[i][j] in row order: A[0][0], A[0][1], ..., A[0][511], A[1][0], ... This is exactly the order data is laid out in memory (C row-major). Every 16 consecutive elements share one 128-byte block. The first element of each block causes a miss; the next 15 are hits. M1 = (512 x 512) / 16 = 262144 / 16 = 16384 misses.
- Compute M2 for P2 (column-major access): P2 iterates A[0][j], A[1][j], ..., A[511][j] for each j. Consecutive accesses in the inner loop are 4096 bytes apart (stride = 1 row). The cache has 256 lines. After 256/32 = 8 steps, line numbers repeat: A[0][j] and A[8][j] map to the same cache line, so A[8][j] evicts the block holding A[0][j]. When we revisit A[0][j]'s neighbors in the next column iteration the block has been evicted. In effect, every access in the column traversal misses the cache. M2 = 512 x 512 = 262144 misses.
- Compute ratio M1/M2: M1 / M2 = 16384 / 262144 = 1/16.