그림으로 배우는 Linux 구조 - 8 / 메모리계층
By Bys on January 8, 2025
메모리 계층
컴퓨터에는 다양한 기억장치가 있고 위의 구조처럼 위로 갈수록 접근 속도는 빠르지만 크기가 작고, 용량 대비 가격이 높아집니다.
캐시 메모리
CPU 동작을 단순히 표현하면 다음과 같은 동작의 반복입니다.
- 명령을 읽고 명령 내용에 따라 메모리에서 레지스터로 데이터를 읽어 들입니다.
- 레지스터에 있는 데이터를 가지고 계산합니다.
- 계산 결과를 메모리에 다시 저장합니다.
레지스터에서 처리하는 계산 시간에 비하면 메모리 접근 속도는 무척 느립니다. 따라서 처리 2가 아무리 빠르더라도 처리 1과 처리 3에서 병목 현상이 일어나서 전체 처리 속도는 늦어집니다.
이런 문제를 해결하는 방법으로 캐시 메모리(cache memory)가 있습니다. 일반적으로 캐시 메모리는 CPU 내부에 존재하는 고속 기억장치입니다. CPU에서 캐시 메모리에 접근하는 속도는 일반 메모리에 접근하는 속도에 비해 수배~ 수십 배 빠릅니다.
메모리에서 레지스터로 데이터를 읽어 들일 때, 일단 캐시 메모리에 캐시라인(cache-line) 이라고 부르는 단위로 데이터를 읽어서 그 데이터를 레지스터로 옮깁니다. 캐시라인 크기는 CPU 마다 정해져 있습니다. 이런 처리는 하드웨어에서 이뤄지므로 커널은 관여하지 않습니다.
다음과 같은 가상적인 CPU 를 예로 들어 캐시 메모리가 하는 일을 살펴봅니다.
- 레지스터는 R0, R1 두 종류이며, 둘 다 크기는 10 바이트
- 캐시 메모리 크기는 50 바이트
- 캐시라인 크기는 10 바이트
우선 CPU R0 메모리 주소 300의 데이터를 읽어 옵니다.
CPU 가 주소 300의 데이터를 다시 읽는다면, 예를 들어 R1 으로 읽어 온다면 메모리에서 가져오는 대신 캐시 메모리에 곧바로 접근하며 되니까 빠르게 처리가 가능합니다.
8-03 상태에서 R0 값을 변경하고 변경된 내용을 메모리 주소 300에 반영한다면 메모리에 쓰기 전에 캐시 메모리에 먼저 저장합니다. 이때 캐시라인에는 메모리에서 읽어 들인 데이터가 변경되었다는 것을 뜻하는 표시를 붙입니다. 이런 표시가 붙은 캐시라인을 더티(dirty) 하다라고 이야기 합니다.
이런 더티 표시가 붙은 캐시라인의 데이터를 메모리에 반영하면 캐시라인에 붙은 더티 표시가 사라집니다. 메모리에 데이터를 쓰는 방법에는 write-through(바로 쓰기) 방식과 write-back(나중에 쓰기) 방식의 두 종료가 있습니다. write-through 는 데이터를 캐시 메모리에 씀과 동시에 메모리에도 바로 기록합니다. 반면에 write-back 은 나중에 정해진 때가 되면 기록합니다. write-through 는 구현이 간단하고, write-back 은 CPU 에서 메모리로 데이터를 쓰는 명령어를 실행할 때 곧바로 메모리에 접근하지 않아도 되므로 처리속도가 빠릅니다.
캐시 메모리가 가득 찼는데 캐시에 존재하지 않는 데이터를 읽어 들이면 기존의 캐시라인 중에서 하나를 버리고 빈 캐시라인에 새로운 데이터를 넣습니다. 예를 들어 주소 350의 데이터를 읽으면 캐시라인 데이터 하나를 버리고(주소 340-350 필드) 지금 비운 캐시라인에 읽어 올 주소의 데이터를 복사합니다.
만약에 이때 버리는 캐시라인이 더티 상태라면 메모리에 데이터를 저장하는 클린(clean) 처리를 하고 버립니다. 캐시 메모리가 가득찬 상태로 계속해서 캐시되지 않은 메모리 영역에 접근하면, 캐시라인 내부 데이터가 빈번히 교체되는 스래싱(thrashing) 상태가 되어서 처리 성능이 떨어집니다.
참조 지역성
만약 CPU 가 사용하는 데이터가 전부 캐시 메모리에 존재한다면, CPU 가 메모리에서 레지스터로 데이터를 읽어 오는 명령을 실행할 때 캐시 메모리 접근만으로 모든 처리가 끝납니다. write-back 방식을 사용한다면 레지스터에서 메모리에 데이터를 쓰는 처리도 캐시 메모리에 쓰면 끝 입니다. 이런 꿈 같은 일이 정말로 일어날까 싶겠지만 실제로는 꽤 자주 발생합니다. 많은 프로그램에서 참조 지역성(Locality of references) 이라고 하는 다음과 같은 특징이 존재합니다.
- 시간적 지역성(Temporal locality): 어떤 시점에 접근하는 메모리는 가까운 미래에 또다시 접근할 가능성이 높습니다. 반복 처리 내부에 존재하는 코드가 전형적인 예입니다.
- 공간적 지역성(Spatial locality): 어떤 시점에 메모리에 접근하면 가까운 미래에 그 근처에 있는 데이터에 접근할 가능성이 높습니다. 배열 요소 전체를 순서대로 조사하는 배열 데이터가 전형적인 예입니다.
따라서 프로세스가 메모리에 접근하는 모습을 관찰할 때 어떤 짧은 기간으로 한정하면, 프로세스 시작부터 종료할 때까지 사용하는 메모리 총량에 비교했을 때 무척이나 적은 메모리만 사용하는 편입니다.
이때 사용하는 메모리 용량이 캐시 메모리 용량으로 충분히 처리할 수 있으면 앞에서 말한 이상적인 고속 처리를 기대할 수 있습니다.
계층형 캐시 메모리
Reference
- 그림으로 배우는 리눅스 구조 (다케우치 사토루)
- E-Book
book
linux
memory
]