Cache Coherence Problem

  • Single memory location에 대해 가장 최신의 값을 읽어야 하는 문제
  • 여러 프로세서가 private cache를 가지고 있기 때문에 발생 가능
    • 쓰기를 해도 write-back과 같은 policy를 사용하면 다른 프로세서는 stale value를 읽게 된다.
    • Shared cache에서는 발생하지 않음

Solutions to the Cache Coherence Problem

  • Software based vs Hardware based
    • Software based
      • 하드웨어 방식과 혼합되어 사용되기도 함
      • 병렬성과 앨리어싱(다른 이름으로 동일한 메모리에 접근하는 것)을 포함해 메모리 접근에 대한 정보를 모두 알고 있어야 한다
    • Hardware based
      • 더 일반적임
      • Snoopy, directory-based protocol 등이 존재
        • e.g. MSI, MESI, MOESI …
        • M: Modified, S: Shared, I: Invalid, E: Exclusive, O: Owner …
      • Coherence miss라는 개념이 등장함
        • Invalidation-based 솔루션의 경우, 다른 프로세서에서 invalidation을 해서 미스가 발생할 수 있음

Snooping

  • 모든 프로세서가 다른 프로세서의 메모리 접근을 감시(snoop)하는 방식
    • Memory bus에 어떤 address가 주어지는지를 바탕으로 감시
    • 누군가 읽기 요청을 했는데, 자신이 해당 address의 dirty copy를 캐시 블록에 가지고 있으면 메모리 접근을 abort 시키고 read requestor에게 직접 캐시 블록을 제공함

Coherence and Write through Caches

  • 쓰기를 할 때 전역 버스 쓰기가 이루어지니 상대적으로 간편함
    • 해당 정보를 보고 다른 캐시를 invalidate하거나 update해야 함
  • 모든 메모리가 up to date value를 가지고 있음

False Sharing

  • Invalidation based cache coherence 프로토콜이 퍼포먼스가 떨어지는 원인이 됨
    • 불필요한 invalidation이 필요
  • Write back, write allocate 캐시를 생각해 보자
    • 아래와 같이, 실제로는 서로 다른 영역을 사용하고 있는데 캐시 라인이 겹치는 바람에 불필요하게 invalidate됨
  • Invalidation based protocol에서 발생하는 문제
    • 메모리 레이아웃을 수정하면 해결된다
    • 데이터 배치를 조정하는 것
  • Update based protocol에서는 값 전달만 하므로 일어나지 않는다

Tiling

Strip mining

  • Operation의 granularity를 조정하는 것
    • Loop를 여러개로 나누는 등
    • 주로 1차원 데이터에 대해 granularity를 조정하면 사용하는 용어이다
  • Vectorization에 주로 사용된다
    • Vector register는 길이가 한정적이므로 딱 맞게 수정하는 것

Tiling for Matrix multiply

Naïve implementation

  • 캐시가 최소 하나의 row나 column을 담을 수 있다고 가정하자. m이 캐시라인의 원소 수라고 할 때, 위와 같은 구현에서 캐시 미스의 수는?
    • 계산에는 a에서 회, b에서 회 미스가 발생
    • i는 N회 a에서 회 미스 (a는 적어도 j Loop에서는 재사용됨)
    • i, j는 각각 N회 b에서 회 미스
    • 이게 피피티 계산인데 약간 이상하다
        1. 최소 하나의 row or column을 담을 수 있는 캐시인데, 만약 딱 하나의 row만 담을 수 있다면 a의 row는 j loop에서 재사용되지 못할 것임 (b나 c를 담으면서 쫒겨날 것이기 때문) 그런데 계산은 a의 row가 재사용된다고 가정함
        1. 설령 하나가 넘는 row or column을 담을 수 있는 캐시라고 해도 c에서 나오는 미스를 계산하지 않았음. 답은 이어야 함
  • +) 만약 원소 하나가 캐시블록 사이즈이고, 캐시 하나가 row 전체를 담지 못한다면 캐시 미스의 수는?
    • a, b, c 각각 미스, 총
    • c를 inner loop 밖에서 접근한다면
  • 각 루프에 대해 strip mining을 적용한다면?

Tiling

  • 3개의 B X B는 캐시가 다 담을 수 있어야 한다
for (kk=0; kk<N; kk += B)
	for (i=0; i<N; i++)
		for (j=0; j<N; j++)
			for (k=kk; k< MIN(kk+B, N); k++)
				c[i][j] += a[i][k] * b[k][j]

for (jj=0; jj<N; jj += B)
	for (kk=0; kk<N; kk += B)
		for (i=0; i<N; i++)
			for (j=jj; j<MIN(jj+B, N); j++)
				for (k=kk; k< MIN(kk+B, N); k++)
					c[i][j] += a[i][k] * b[k][j]

for (ii=0; ii<N; ii += B)
	for (jj=0; jj<N; jj += B)
		for (kk=0; kk<N; kk += B)
			for (i=ii; i<MIN(ii+B, N); i++)
				for (j=jj; j<MIN(jj+B, N); j++)
					for (k=kk; k< MIN(kk+B, N); k++)
						c[i][j] += a[i][k] * b[k][j]

  • 각 서브블록이 스칼라처럼 계산되는 것이라 볼 수 있다

Evaluation

  • 캐시가 세개의 BXB 블록을 담을 수 있다고 가정하면
    • a, b 각각에 대해 하나의 블록을 로드하는 데에 필요한 미스
    • 회 로드하므로
    • 마찬가지로 c는 계산하지 않음
  • 아까보다 에 곱하는 수가 작아져서 좋음