"큰 데이터를 한 번에 다루지 말고, 작은 덩어리(block)로 쪼개서 처리하자."
for (i = 0; i < N; i++)
for (j = 0; j < N; j++)
for (k = 0; k < N; k++)
C[i][j] += A[i][k] * B[k][j];
이 코드는 단순하지만, 실제로는 캐시가 자주 미스 납니다.
왜냐하면 A, B, C가 너무 커서 한 번 읽은 데이터가 캐시에서 금방 쫓겨나기 때문이죠.
그래서 Blocking을 씁니다:
for (ii = 0; ii < N; ii += B)
for (jj = 0; jj < N; jj += B)
for (kk = 0; kk < N; kk += B)
// 작은 BxB 블록끼리만 곱함
for (i = ii; i < ii + B; i++)
for (j = jj; j < jj + B; j++)
for (k = kk; k < kk + B; k++)
C[i][j] += A[i][k] * B[k][j];
이제 프로그램은:
A, B, C의 작은 블록 하나씩을 캐시에 불러옴이렇게 하면 같은 데이터(예: A[i][k])를 캐시에 있을 때 여러 번 사용합니다 → 시간적 지역성 향상
본문의 마지막 문장:
“Blocking does not improve the performance of matrix multiply on the Core i7, because of its sophisticated prefetching hardware.”
즉, Blocking은 이론적으로 강력하지만,
하드웨어가 단순한 시스템(임베디드, 구형 CPU 등)에서 더 유용합니다.