캐시 라인(Cache-Line)

· 1393 words · 3 minute read

캐시를 꼭 사용해야 하나 🔗

SMP 환경에서 일어나는 커널 패닉 문제를 다루다 보면 메모리 배리어를 비롯하여 캐시와 주 메모리 간의 동기화를 다루는 내용이 주를 이룬다. 하지만 매번 간략하게 정리한 문서가 없다보니 기억에 잘 남지도 않고 전체적인 흐름을 읽지 못하는 것 같아 이번 포스팅을 통해서 대략적으로나마 정리하고자 한다.

프로세서 캐시와 메모리의 불일치 문제는 다루기 까다로운 문제이다. 단순하게 프로세서가 싱글 코어라면 문제가 없겠지만 여러 개의 코어를 가지고 있는 프로세서라면 각각의 코어가 가지고 있는 캐시와 주 메모리를 동기화 시켜주어야 한다. 그러한 동기화로 인해 캐시 성능이 제대로 나오지 않을 것 같은데도 ‘코어 ~ 캐시’의 액세스 속도와 ‘코어 ~ 주 메모리’ 간의 속도 차이가 그러한 동기화 이슈를 가릴 정도로 충분히 크기 때문에 여전히 필자가 보이게 변태같은 구조로 열심히 캐시를 사용하고 있다.

주 메모리의 내용을 캐시에 저장하기 위해서 주 메모리의 데이터를 읽어와야 한다. 이 때, 읽어들이는 최소 단위를 캐시라인(cahce-line)이라 하며, 이렇게 읽어들인 데이터는 캐시의 data block을 구성하게 된다. 캐시는 아래와 같이 간략하게 나타낼 수 있다.

 +------------------------ cache --------------------------------------+
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 | +-----------------------------------------------------------------+ |
 | | memory address |  status bit  |    data block                   | |
 | +-----------------------------------------------------------------+ |
 |                                                                     |
 |                                                                     |
 |                                                                     |
 +---------------------------------------------------------------------+

메모리 주소의 일부를 이용하여 만든 태그와 해당 캐시라인의 상태(invalid or modified)를 나타내는 상태 비트, 그리고 데이터 블록으로 구성된다. 캐시 정책에 따라 구조가 조금씩 달라지기는 하지만 대략적인 개념은 위와 같으며, 포인트는 메모리의 데이터를 워드 단위가 아닌 “cache-line"의 크기 단위로 읽어들이며, 해당 데이터의 메모리 주소를 이용하여 태그로써 관리한다는 점이다.

캐시 관리 방법 🔗

캐시를 관리하는 방식으로 Full Associative, Set Associative, Direct Mapped 등이 있다.

먼저 제일 간단한 “direct map” 방식부터 살펴보면, 메모리 주소의 일부를 인덱스(위에서 태그로 표현한 부분)로 사용하여 관리하는 방식이다. 이러한 방식 때문에, 같은 인덱스를 갖는 메모리가 인접하여 액세스되는 경우 cache miss가 발생할 수 있다. 데이터 블록 크기만큼 캐시되지 않으면서, 주소의 부분만을 인덱스로 사용하는 방식이기 때문에 캐시되지 않은 인접 데이터로 인해 cache miss가 발생하는 시나리오다.

다음은 “Full Associative” 방식으로 쉽게 설명하면 비어있는 캐시메모리가 있으면 그냥 마음대로 주소를 저장하는 방식이다. 이 때문에, 반드시 DRAM이 아닌 SRAM을 사용해야 하며 저장할 때는 크게 알고리즘이 필요없어서 간단한데, 찾을 때가 문제다. “어떠한 조건이나 규칙이 없으니 특정 캐쉬 Set내의 모든 블럭을 한 번에 찾아 원하는 데이터가 있는지 검사해야 하며” 이를 위해 CAM (Content Addressable Memory) 라는 특수한 형태의 메모리 구조를 사용해야 한다. 여기서는 인덱스 대신 index + tag 조합으로 된 태그 부분으로 구성된다.

마지막으로 Set Associative 방식이다. 여러 개의 Direct Mapped 방식으로 나누어 사용한다고 생각하면 된다. 본래 메모리 주소의 일부만을 이용하여 태그로 사용하는 Direct Mapped 방식이기에 이를 2개, 4개로 구성한 여러 개의 Direct Mapped 방식에 Multiplexer와 OR gate를 조합하여 아래와 같이 구성한다.

+---------------------+-----------------+----------------+--------------+
| memory address      |                 |                |              |
+----------+----------+--------+--------+--------+-------+--------------+
           |                   |                 |
           |                   |                 |
           |                   |                 |
           |                   |                 |
           v                   v                 +---------v
+----------+----------+  +-----+---------------+  +---------------------+
| direct|mapped cache |  | direct|mapped cache |  | direct|mapped cache |
+----------+----------+  +----------+----------+  +----------+----------+
           |                        |                        |
           +------------------------+---------+--------------+
           |                                  |
+----------v-------------------------+    +---v-----+
|       multiplexer                  |    | OR Gate |
+------------------------------------+    +---------+

출처 🔗