stripe of A is loaded, and the entire matrix B is loaded. For the entire calculation, C is stored once (that's good), A is loaded into the cache once (assuming a stripe of A fits in the cache with a stripe of B), but B is loaded N/ib times, where ib is the size of the strip in the C matrix, for a total of N3/ib doubleword loads from main memory. In the code above, ib is 2. The next step to reduce the memory traffic is to make ib as large as possible. It needs to be larger than the "balance" number reported by streams. In the case of one particular 2.8 GHz Pentium 4 system used for this example, the balance number is 16.5. The second code example above cannot be extended directly, since that would require many more accumulator registers. Instead, the loop is blocked over i. (Technically, this is actually the second time i is blocked, as the first time was the factor of 2.) for (ii = 0; ii < N; ii += ib) { for (j = 0; j < N; j += 2) { for (i = ii; i < ii + ib; i += 2) { acc00 = acc01 = acc10 = acc11 = 0; for (k = 0; k < N; k++) { acc00 += B[k][j + 0] * A[i + 0][k]; acc01 += B[k][j + 1] * A[i + 0][k]; acc10 += B[k][j + 0] * A[i + 1][k]; acc11 += B[k][j + 1] * A[i + 1][k]; } C[i + 0][j + 0] = acc00; C[i + 0][j + 1] = acc01; C[i + 1][j + 0] = acc10; C[i + 1][j + 1] = acc11; } } } With this code, ib can be set to any desired parameter, and the number of loads of the B matrix will be reduced by that factor. This freedom has a cost: N×ib slices of the A matrix are being kept in the cache. As long as that fits, this code will not be limited by the memory system. So what size matrix fits? The example system, a 2.8 GHz Pentium 4, has a 16KB primary data cache. With ib=20, the slice of the A matrix in this code will be larger than the primary cache when N > 100. For problems larger than that, another trick is needed. That trick