floatFirstTOC: right
🖥️ 들어가며🔍 캐시(Cache)란?💡 메모리 구조🔍 캐시 메모리 ‘자주 사용하는 데이터’ 특성📌 시간적 지역성📌 공간적 지역성🔍 캐시의 구조📌 워드 (Word)📌 블록 (Block)📌 캐시 (Cache)🔍 캐시의 작동 방식📌 인덱싱📌 태그 매칭과 Vaild📌 Offset의 사용처💡 여전한 의문점 : 이 이미지는 무엇인가?🧷 참고 문헌
🖥️ 들어가며
자꾸 헷갈렸던 캐시 메모리의 총정리를 해보려고 한다. 왜 이리 헷갈리는지 드디어 가닥을 잡은 것 같아 포스팅으로 이 기억을 남기려고 한다.
🔍 캐시(Cache)란?
프로세스는 트랜지스터의 등장 이후 굉장히 빠른 속도로 발전한 반면, 메모리의 발전 속도는 프로세서에 비해 굉장히 더디게 발전했다. 이런 속도 간격을 메꾸기 위해
캐시(Cache)
가 나오게 되었다.캐시는 CPU 안에 들어가는 매우 빠른 메모리다. 자주 사용하는 데이터들은 미리 캐시에 넣어둔 후, 프로세서가 메인 메모리 대신 캐시에서 데이터를 가져오도록 해 처리 속도를 높이는 것이 목적이다.
💡 메모리 구조
그림에서 보는 바와 같이, 속도는 위로 올라갈수록 빨라지고 용량은 위로 올라갈수록 적어진다. 그리고 가장 중요하게 알아 둬야 할 것은 인접한 두 계층 사이에서만 데이터 전송이 일어난다는 것이다.
그럼 이러한 질문이 나올 수 있다.
왜 레지스터랑 캐시 메모리를 많이 만들지 않나요?
여러 이유가 있지만, 우선 가장 큰 이유는 비용이다. 또한 레지스터나 캐시 메모리는 작기 때문에 빠르다는 특성을 가지고 있다. 작아야 전기 신호가 빠르게 이동하고, 데이터에 더 빠르게 접근할 수 있기 때문이다.
🔍 캐시 메모리 ‘자주 사용하는 데이터’ 특성
자주 사용하는 데이터
의 기준은 지역성을 따른다.📌 시간적 지역성
한번 참조된 항목은 곧바로 다시 참조되는 경향을 말한다.
가장 간단한 예는 반복문이다.
for (int i = 0; i < 10; i++) { arr[i] = i; }
여기서 변수
i
는 곧바로 계속 참조되는 경향이 있다.📌 공간적 지역성
참조된 어떤 항목 근처의 다른 항목들이 곧바로 다시 참조되는 경향을 말한다.
이것도 반복문을 보면 쉽게 알 수 있다.
for (int i = 0; i < 10; i++) { arr[i] = i; }
arr
의 요소는 붙어있으므로 근처 요소들이 곧바로 다시 참조된다.🔍 캐시의 구조
먼저 캐시를 알기 위해서는
워드
와 블록
을 알아야 한다. 또한 대전제로, 메모리는
1byte
단위로 취급된다는 것도 알아야 한다. bit 단위가 아니다!📌 워드 (Word)
메모리에서 데이터를 액세스하는 기본 단위이다. 보통
32bit
운영체제에서는 32bit
, 즉 4B
가 데이터 엑세스 기본 단위이다.📌 블록 (Block)
데이터의 기본 저장 단위이다. 각 블록은 특정 크기(예 :
32B
)의 데이터를 저장하며, 여러 개의 워드를 포함한다.즉 블록이
32B
의 데이터를 저장하면 32bit 운영체제에서 워드의 크기는 4B
이니 4개의 워드가 포함된다.📌 캐시 (Cache)
여러 개의 블록들의 집합이다. 즉 캐시의 크기는 블록이 몇 개 있는지에 따라 결정된다.
예를 들어, 각 블록이
32B
를 저장할 수 있고 총 1024개의 블록
이 있다면, 캐시의 전체 크기는 32B
× 1024 블록
= 32,768B (32KB)
가 된다.그림으로 나타내면 다음과 같다.
🔍 캐시의 작동 방식
이제 캐시가 어떻게 작동하는지 알아야 한다.
CPU에서 요청한 데이터가 캐시에 존재할 때
캐시 히트 (Hit)
라고 한다. 캐시에 존재하지 않으면 미스 (Miss)
났다고 하며, 하위 메모리에서 다시 값을 가져와야 한다.그렇다면 CPU에서 어떤 메모리에 존재하는 데이터를 가져오기 위해 주소가 주어졌을 때, 어떻게 이 데이터가 캐시에 존재하는지, 즉
Hit
날 것인지 알 수 있을까?여러 방법이 있지만, 일단 여기서는
Direct Mapping Cache
에 대해 설명하려고 한다.📌 인덱싱
캐시는 당연하게도 메모리보다는 작으므로
32bit
전체를 가지고 바로 캐시로 접근할 수는 없다. 그러므로 Indexing
작업을 통해 접근한다.위에서 가정했던 바와 같이 캐시 블록의 수가 1024개, 블록 사이즈가 32바이트라고 가정하자.
→ 이므로 캐시 블록의 개수를 나타나는 데
10bit
가 필요하다.→ 받은 전체 주소에서 하위
5bit
를 Offset
으로 지정하고, 이후 10bit
를 Index
로 사용해 캐시 블록에 접근한다. 그러나 이렇게만 사용한다면 캐시에 데이터가 존재한다면 이 데이터가 요청한 데이터가 맞는지 알기 힘들다. 중복되는 데이터가 굉장히 많기 때문이다.
그렇기에 이런 충돌을 줄이기 위해
Tag
와 Vaild
를 사용한다.📌 태그 매칭과 Vaild
- 주소의
Index
를 찾아 캐시로 들어간다.
Vaild
값이 0이라면 데이터가 없던 것, 1이라면 데이터가 있던 것이다. 0이라면 하위 메모리 계층에서 데이터를 갖고 와야 한다.
Tag
를 비교해 일치하면 원하든 데이터인 것이므로Hit
처리하고Data
를 반환한다.
📌 Offset의 사용처
오프셋
은 데이터의 정확한 위치를 찾기 위해 사용한다.캐시에는 여러 블록이 있고, 물론 주소가 하나의 블록을 가리키지만 블록에도 여러 워드가 존재한다.
만약 블록이
32B
라 가정하자. 이므로 블록 내부 데이터를 가리킬 때 5bit
가 필요하다.즉, 더 빠르게 데이터에 접근하기 위한 값이라 할 수 있다.
워드를 다시 생각해보자. 블록이
32B
라면 워드는 4B
이기 때문에 블록에 8개의 워드가 들어간다.→ 이므로 워드의 위치를 나타내는 데에
3bit
가 필요하다.총 정리하면 아래와 같다.
- 상위 3비트 (비트 2, 3, 4): 이 비트들은 블록 내에서 워드의 위치를 선택하는 데 사용된다. 이 비트들은 0부터 7까지의 값을 가지며, 블록 내에서 각 워드의 시작 바이트를 지정한다.
- 하위 2비트 (비트 0, 1): 이 비트들은 워드 내에서 바이트의 위치를 지정하는 데 사용된다. 워드가 4바이트이므로, 이 2비트는 워드 내에서 0부터 3까지의 바이트 위치를 선택하는 데 필요하다.
💡 여전한 의문점 : 이 이미지는 무엇인가?
여기서는 태그 배열이 존재한다고 하셔서.. 어렵다 어려워. 내가 찾은 다른 참고자료들에는 이런 자료가 없어서 헷갈린다. 그래도 밑에 끄적여보였다.
🧷 참고 문헌
그리고 교수님 감사합니다..
댓글