12.5 캐시 메모리
-
컴퓨터가 어떤 동작들을 수행할 때, 그 동작들에 필요한 데이터를 가져오기 위해 메모리에 접근하게 된다. 그리고 메모리에사 특정한 데이터를 참조해오기 위해 메모리에 한정된 지역내에 있는 데이터를 참조해오는 경향이 있다. - 참조의 국한성 (Locality of reference)
-
우리는 컴퓨터의 성능을 향상시키기 위해서 자주 참조되는 메모리의 특정 영역만 더 빠른 메모리에 저장해두면 그러면 평균적인 메모리 접근시간도 감소하고, 따라서 프로그램을 실행하는 총 수행시간이 단축될 거라고 예상할 수 있다. 그게 바로 캐시메모리 이다. - 작지만 빠른 메모리 (캐시메모리)
-
캐시메모리 : 가장 자주 접근하는 명령어와 데이터를 캐시메모리 안에 저장해두는 형태로 사용한다.
-
캐시메모리의 설계 구성요소
-
-
캐시 사이즈 : 256 K byte (최대 512 K byte)
맵핑 방법 : 1) associative 2) direct 3) set-associative
-
replace 알고리즘 : 1) LRU 2) LFU 3) FIRO
-
데이터를 쓰는 정책 : 1) write-through 2) write-back
-
히트율
- 캐시메모리의 성능을 측정하는데 사용하는 수치
- 일반적으로 CPU가 메모리를 참조할 때 캐시 메모리에 있는 데이터를 먼저 확인한다. 캐시 메모리에 데이터가 없으면 주기억장치에 있는 데이터를 확인한다. 찾고자 하는 데이터가 캐시메모리에 있다면 CPU가 연산을 보다 빠르게 할 수 있다.
-
- hit : 캐시 메모리 내에서 word를 찾았을 때 (일반적으로 0.9)
- miss : 캐시 메모리 내에서 word를 찾지못했을 때
-
hit 수가 클수록 CPU가 캐시메모리에서 가져와서 연산을 수행했다고 할 수 있다.
- ex) 캐시메모리 접근시간이 100ns 이면 주 메모리 접근시간은 1000ns이다. hit율은 0.9이다.
-
- 1 miss : 1 x 1000ns
- 9 hit : 9 x 100ns
-
- 1900 ns / 10 times = 190 ns = 평균 접근 속도
캐시메모리의 맵핑 과정
- 메인 메모리로부터 캐시메모리로 데이터를 전송하는 과정
- 1) Associative mapping
- 2) Direct mapping
- 3) Set-associative mapping
캐시메모리 예제
- 메인 메모리 크기 : 32K X 12 bits (15 bits address lines)
- 캐시 메모리 크기 : 512 X 12 bits
-
- CPU는 15비트 주소를 캐시로 보낸다.
-
- hit : 캐시 메모리로부터 12비트 데이터를 찾아서 가지고 온다.
- miss : CPU는 다시 메인 메모리로부터 데이터를 읽어온다. (캐시에 데이터를 쓴다)
Associative mapping
- associative memory를 사용하여 캐시메모리를 구성하는 방법
- 캐시메모리에 있는 데이터를 주소부분과 데이터부분으로 나누어서 직접적으로 사용된다.
- 어드레스에 해당하는 데이터들을 모두 확인했는데 지금 찾고자 하는 데이터가 없으면, 즉 15비트와 같은 주소가 없으면 메인메모리에서 해당 주소에 접근해서 그 주소에 있는 데이터를 가지고 오는 형태로 동작한다. 그 내용이 캐시 메모리에 추가된다.
- 27비트가 하나의 워드로 사용되고 있다.
- 단순하고 빠르게 특정 데이터 내용을 검색해서 전달할 수 있다.
Direct mapping
- 캐시메모리가 앞에서 봤었던 associative 메모리보다 경제적인 일반적인 메모리를 사용한다.
- n 비트의 메모리 주소를 두개의 필드로 나누어서 표현한다.
-
- k 비트가 index 필드
- (n-k)비트를 태그 필드
- n = 메인 메모리에 워드를 나타내는 비트수
- k = 캐시 메모리의 워드를 나타내는 비트수
- 앞에 남아있는 비트를 태그필드라고 부른다.
-
- ex) 주소 =15비트, 태그=6비트(15-9), index= 9비트
직접 맵핑 방식을 사용한 캐시메모리 구조
- 인덱스 주소만을 가지고 표현되는 주소값이 캐시의 주소값이다.
- 메인 메모리는 15개 비트를 모두 사용해서 표현되게 된다.
- 예) CPU가 메모리 주소 02000에 접근하는 경우를 예를 들어서 살펴보자.
-
- 1) 첫번째로, 인덱스 필드에 해당하는 값을 캐시에서 확인한다.
- 2) 태그 필드를 비교한다. 캐시 주소에 000에 해당하는 주소에서 같은지 비교한다.
- 3) 만약 인덱스 필드 주소에서 해당 캐시 태그가 같으면 00(찾아짐), 다르면 02로 표시한다.
- 4) 02이면 miss다. 못찾은 경우다
- 5) 메인 메모리에서 데이터를 읽어온다. 주소는 02000에 해당하는 위치 데이터는 5670를 CPU로 read 된다.
-
캐시메모리에는 종종 하나의 워드가 아니라 8개의 워드처럼 일정한 블록이 한번에 전송되는 경우들이 있다. 왜냐하면 특정한 데이터를 캐시에서 찾지 못했을 때 해당 워드만 캐시에서 사용되는게 아니라 다음 워드도 CPu에서 요구할 확률이 크다. 그래서 miss가 발생했을 때 miss 가 발생한 하나의 word만 캐시로 가지고 오는 것이 아니라 메인 메모리에서 일정한 블록에 있는 여러개의 word들을 모두다 캐시에 가져오는 형태로 동작시킬 수 있다.
-
물론 8개의 워드를 하나의 블록으로 만들면 한번 미스가 일어났을때 8개의 워드를 캐시로 옮겨야 하니까 조금 번거로울 수 있다. 그렇다고 하더라도 8개의 워드를 가지고 오는데 hit율을 향상시키는데 도움이 된다.
set-associative mapping : two-way
- 다이렉트 맵핑 방식의 단점을 해결하기 위해서 만들어진 방식이다.
- 다이렉트 맵핑 방식의 문제는 인덱스 필드와 태그 필드로 나눈것은 좋은데, 인덱스 필드를 찾아서 갔더니 태그가 다른 경우가 생각보다 많다. 예를 들면 02777과 01777 같은 경우 777에 해당하는 주소에 저장될 수 있는 태그가 하나밖에 없다. 그래서 인덱스를 먼저 검색한 후 태그를 확인하는 형태로 동작이 그렇게 빠르지 않을 수도 있는 경우가 있다. 그래서 하나의 인덱스에 저장되어 있는 태그와 데이터를 늘리면 그러면 더 빨리 데이터를 읽어올 수 있다.
- 여기서 말하는 set은 하나의 태그 데이터에 태그데이터를 더 추가해서 두개의 세트로 묶어서 표현한 방식이다.
- 전체 word 길이는 2배로 늘어나지만 검색 속도는 좀 더 빨라 진다.
교체 알고리즘
- CPU가 캐시에서 데이터를 검색한 결과 miss가 발생하거나 캐시에 있는 데이터가 모두 차 있는 경우 교체 알고리즘에 의해 데이터가 교체되게 된다.
- LRU (Least Recently used) : 최근에 사용되지 않은 block 교체
- LFU (Least Frequently Used) : 사용 빈도가 가장 적은 block 교체
- FIFO (First-In First-Out) : 가장 오래된 block 교체
Writing to cache : cache coherence
- CPU가 캐시로부터 어떤 데이터를 가져다가 연산을 하고, 그 결과를 다시 캐시에 있었던 내용에 업데이트 할 수 있다. 이 때 주의할 점은 캐시에 저장되어 있는 데이터와 메인 메모리에 저장되어 있는 데이터는 같아야 한다는 것이다. 그래서 만약에 CPU가 캐시에 있는 내용을 변경한다면 메인 메모리에 있는 내용도 변경되어야할 필요가 있다.
-
- 메인 메모리와 캐시 메모리의 내용이 동일해야함 : 일관성 유지
1) Wirte-through : 캐시에 어떤 데이터를 쓸때 동시에 메인 메모리에도 동시에 써주는 방식
2) Write-back : 캐시메모리에 write할 때 내용이 변경되었다는 flag만 해놓고 나중에 block이 교체되기전에 flag를 검사하여 변경된 부분만 write한다. 따라서 write-back 방식은 메인 메모리가 무효한 상태에 빠져 있을 수 있다. CPu와 캐시 메모리가 동시에 메인 메모리에 접근하는 상황에 빠질 수 있다.
캐시 초기화
1) 컴퓨터에 전원이 들어왔을때
2) 보조 메모리로부터 어떤 프로그램이 메인 메모리로 로그되었을 때
초기화되는 형태의 동작이 수행된다.
캐시메모리는 어떤 데이터를 저장할 때 그 데이터를 유효한지 아닌지 표현하기 위해서 valid bit를 포함하고 있다. 그리고 초기화가 되는 동작이 실행될때 valid bit 를 0으로 만든다. 메인메모리로부터 어떤 데이터가 전달되면 해당 word가 유효하다는 것을 표현하기 위해 valid bit를 1로 변경해준다.