포스트

주기억 장치

주기억 장치

주기억 장치(Main Memory)

CPU와 가장 가까운 메모리 계층으로, CPU가 직접 접근하여 명령어와 데이터를 읽고 쓸 수 있는 작업공간입니다. 보조 기억 장치(SSD, HDD)에 저장된 프로그램과 데이터는 실행되는 순간 주기억 장치에 적재(Load)되어야 합니다.

주기억 장치의 역할

  • 프로그램 명령어 저장 : 실행 중인 프로그램의 명령어가 저장되며, CPU는 명령어를 명령어 사이클(인출 → 해독 → 실행)에 따라 처리합니다.
  • 데이터 저장 : 프로그램이 처리하는 데이터가 저장되며, 연산 중인 중간값과 최종 결과도 저장합니다.
  • CPU와 저장장치 간 데이터 중계 : 주기억 장치는 CPU와 하드디스크(보조 기억 장치) 사이에서 데이터를 빠르게 전달하는 역할을 합니다.

기존 CPU와 하드디스크 간의 속도 차이로 인해 CPU는 데이터를 전달 시 계속 대기해야 하는 현상이 발생하여 이러한 속도 차이를 해결하기 위해 중계 역할을 하는 주기억 장치를 사용합니다.

예를 들어 디스크에 저장된 게임을 실행할 경우 데이터 정보를 메모리로 이동시키고 이를 CPU가 통신하며 필요한 명령어를 처리합니다.

RAM(Random Access Memory)

주기억장치는 주로 RAM으로 만들어집니다. RAM은 이름 그대로 어느 위치든 임의로 접근(Random Access) 하여 동일한 속도로 데이터를 읽고 쓸 수 있는 메모리입니다.

RAM은 전원이 공급되지 않으면 저장된 모든 내용이 사라지는 휘발성 메모리(Volatile Memory) 입니다. 그래서 프로그램과 데이터는 영구 저장을 위해 비휘발성인 보조기억장치에 보관됩니다.

DRAM (Dynamic RAM)

주기적으로 재충전(Refresh) 해줘야 데이터가 유지되는 RAM입니다. 가격이 저렴하고 집적도가 높아 PC의 주 메모리로 널리 사용됩니다.

SRAM (Static RAM)

전원이 공급되는 동안에는 데이터가 계속 유지되는 RAM입니다. DRAM보다 훨씬 빠르지만, 가격이 비싸고 구조가 복잡해 CPU의 캐시 메모리나 레지스터 등 소량의 고속 메모리에 사용됩니다.

주소 공간과 MMU의 주소 변환

프로그램이 실행될 때, CPU와 메모리는 ‘주소’를 통해 소통합니다. 주소 공간은 메모리의 각 위치를 식별하는 고유한 주소의 범위를 의미하며, 메모리의 주소 공간은 물리 주소 또는 논리 주소로 표현합니다.

물리 주소(Physical Address)

실제 주기억장치(RAM)의 하드웨어 상 주소입니다. 메모리 컨트롤러는 이 물리 주소를 통해 실제 데이터 위치에 접근합니다.

논리 주소(logical Address)

CPU가 생성하는 주소이며 각 프로세스마다 독립적으로 할당되는 0부터 시작하는 가상의 주소 공간을 가집니다. 이를 통해 프로그래머나 컴파일러는 실제 물리 메모리가 어떻게 구성되어 있는지 신경 쓰지 않고 프로그램을 작성할 수 있습니다.

논리 주소가 필요한 이유

  • 프로그램이 다른 물리 주소를 갖게 되더라도 CPU에서는 항상 동일한 논리 주소를 참조할 수 있습니다.
  • 프로그램에 독립적인 논리 주소 공간을 할당하여 다른 프로그램의 메모리 침범을 방지합니다.

MMU(Memory Management Unit)

CPU와 주기억 장치 사이에 위치하여, CPU가 생성한 논리 주소를 실제 물리 주소로 변환해주는 하드웨어 장치입니다.

주소 변환 과정

  1. CPU는 특정 데이터에 접근하기 위해 논리 주소를 생성하여 MMU에 전달합니다.
  2. MMU는 페이지 테이블(Page Table) 이라는 변환 정보를 참조하여 해당 논리 주소에 대응하는 물리 주소를 찾습니다. (물리주소 = 베이스 레지스터 + 논리 주소)
  3. MMU는 변환된 물리 주소를 메모리 버스로 보내 실제 주기억 장치에 접근하도록 합니다.

이러한 주소 변환 과정 덕분에 운영체제는 각 프로세스에 독립적인 메모리 공간을 제공하고(메모리 보호), 실제 메모리보다 더 큰 공간을 사용하는 것처럼 보이는 가상 메모리(Virtual Memory) 시스템을 구현할 수 있습니다.

접근 검증

변환된 물리 주소가 베이스 레지스터, 베이스 레지스터 + 한계 레지스터 범위 내에 있는지 확인합니다. 만약 범위를 벗어나면 침범 탐지(트랩 또는 예외 발생) 후 접근을 차단합니다.

  • 베이스 레지스터(Base register) : 현재 프로그램의 메모리 시작 위치를 저장합니다.
  • 한계 레지스터(Limit register) : 현재 프로그램의 메모리 크기(범위)를 저장합니다.
1
2
3
4
5
6
7
8
9
10
11
12
프로그램 A
논리 주소 - 0~30
물리 주소 - 100~130

베이스 레지스터 - 100
한계 레지스터 - 30

CPU가 논리 주소 22에 접근할 때
-> 실제 메모리 주소 122에 접근

CPU가 논리주소 33에 접근할 때
-> 실제 메모리 주소 133은 주소 범위를 벗어나므로 예외 발생

베이스/한계 레지스터를 사용하는 방식은 초기의 세그멘테이션(Segmentation) 기법에서 사용된 간단한 메모리 관리 방식입니다. 현대 운영체제는 메모리를 고정된 크기의 블록으로 나누어 관리하는 페이징(Paging) 기법을 주로 사용하며, 이때 MMU는 페이지 테이블을 참조하여 주소를 변환합니다.

즉, 베이스/한계 레지스터 방식이 원리를 이해하는 데 도움을 주지만, 현재는 페이지 테이블 방식이 표준으로 사용됩니다.

캐시 기억 장치(Cache Memory)

CPU는 내부 저장 장치로 레지스터를 사용하지만, 주기억 장치의 속도가 상대적으로 느려 발생하는 속도 차이로 인해 CPU가 메모리를 기다리며 노는 시간(지연 시간, Latency)이 발생하는데, 이를 CPU-메모리 병목 현상이라고 합니다.

캐시 메모리는 이 문제를 해결하기 위해 CPU와 주기억장치(RAM) 사이에 위치하는 매우 빠른 소용량의 메모리(주로 SRAM 사용)이며, 자주 수행되는 명령어나 피연산자를 미리 주기억 장치에서 가져와 저장합니다.

작동 원리

캐시는 참조 지역성의 원리(Locality of Reference) 를 기반으로 동작합니다.

  • 시간적 지역성(Temporal Locality) : 최근에 접근한 데이터는 가까운 미래에 다시 접근될 가능성이 높다.
  • 공간적 지역성(Spatial Locality) : 특정 데이터에 접근하면, 그 주변의 데이터들도 곧이어 접근될 가능성이 높다. 캐시는 이 원리에 따라 CPU가 자주 사용할 것으로 예상되는 데이터의 복사본을 주기억장치에서 미리 가져와 보관합니다.

동작 과정

  1. CPU가 데이터를 요청하면, 먼저 캐시 메모리를 확인합니다.
  2. 캐시 히트 (Cache Hit) : 원하는 데이터가 캐시에 있으면, 주기억장치까지 갈 필요 없이 즉시 데이터를 CPU에 제공합니다. (매우 빠름)
  3. 캐시 미스 (Cache Miss) : 원하는 데이터가 캐시에 없으면, 주기억장치에서 해당 데이터를 포함하는 블록(Block) 전체를 찾아 캐시로 가져온 후 CPU에 제공합니다. (상대적으로 느림)

다중 레벨 캐시(Multi-level Cache)

현대 CPU는 속도와 크기가 다른 여러 단계의 캐시(L1, L2, L3 캐시)를 계층적으로 사용합니다.

  • L1 캐시 : CPU 코어 내부에 존재하며 가장 작고 빠릅니다. 보통 명령어 캐시(I-Cache)와 데이터 캐시(D-Cache)로 분리됩니다.
  • L2 캐시 : L1보다 크고 느리며, 각 코어에 개별적으로 존재하거나 소수의 코어가 공유합니다.
  • L3 캐시 (LLC: Last Level Cache) : 가장 크고 느리지만, 칩 안의 모든 코어가 공유하는 캐시입니다.

캐시 매핑 방식

주기억장치의 데이터를 캐시의 어느 위치(라인)에 저장할지를 결정하는 정책입니다.

직접 매핑 (Direct Mapping)

가장 간단한 방식으로, 메모리의 특정 블록이 들어갈 수 있는 캐시의 위치가 하나로 고정되어 있습니다. 구현은 쉽지만, 다른 위치가 비어있어도 충돌(Conflict Miss)이 발생할 수 있습니다.

완전 연관 매핑 (Fully Associative Mapping)

가장 유연한 방식으로, 메모리의 블록이 캐시의 어느 위치에나 들어갈 수 있습니다. 공간 활용도는 높지만, 원하는 데이터를 찾기 위해 모든 캐시 라인을 검색해야 하므로 회로가 복잡하고 비용이 비쌉니다.

세트 연관 매핑 (Set-Associative Mapping)

위 두 방식의 장점을 절충한 방식으로, 캐시를 여러 세트(Set) 로 나누고, 메모리 블록은 정해진 하나의 세트 안에서는 어디에나 위치할 수 있습니다. 현대 CPU 캐시에서 가장 널리 사용되는 방식입니다.

캐시 쓰기 정책(Write Policy)

CPU가 데이터를 변경(Write)할 때, 이 변경 사항을 언제 어떻게 캐시와 주기억장치에 반영할지에 대한 정책입니다.

즉시 쓰기 (Write-Through)

CPU가 데이터를 쓸 때마다 캐시와 주기억장치에 동시에 씁니다. 데이터 일관성 유지가 간단하지만, 매번 주기억장치에 접근해야 해서 속도가 느립니다.

지연 쓰기 (Write-Back)

데이터 변경은 우선 캐시에만 반영하고, 해당 캐시 블록이 교체될 때 변경된 내용을 모아 한 번에 주기억장치에 씁니다. 쓰기 속도가 빠르지만, 데이터 불일치가 발생할 수 있어 이를 관리하기 위한 ‘Dirty Bit’ 같은 메커니즘이 필요합니다.

캐시 일관성 (Cache Coherence)

멀티코어 환경에서 여러 코어가 동일한 메모리 데이터를 각자의 캐시에 가지고 있을 때, 한 코어가 데이터를 수정하면 다른 코어의 캐시 데이터가 오래된(stale) 값이 되는 문제가 발생합니다. 캐시 일관성 프로토콜(MESI 프로토콜) 은 모든 코어가 항상 최신 데이터를 볼 수 있도록 보장하여 이 문제를 해결합니다.

성능 척도 : 적중률과 평균 접근 시간

캐시의 성능은 얼마나 CPU가 원하는 데이터를 잘 가지고 있느냐에 따라 결정됩니다.

적중률(Hit Rate)

CPU가 요청한 데이터가 캐시에 존재할 확률입니다. 적중률이 높을수록 캐시의 성능이 좋고, 전체 시스템의 속도가 향상됩니다.

\[적중률(H) = \frac{캐시 히트 횟수}{전체 메모리 접근 횟수}\]
  • 적중률 85% → CPU가 필요한 데이터를 캐시 기억 장치에서 검색할 때, 100번 중 85번은 캐시 기억 장치에 데이터가 존재

평균 기억 장치 접근 시간(Average Memory Access Time, AMAT)

CPU가 데이터에 접근하는 데 걸리는 시간의 평균값입니다. 이 값이 낮을수록 시스템 성능이 좋습니다.

\[T_{avg} = H \cdot T_{cache} + (1 - H) \cdot T_{main}\]
  • 미스율(Miss Rate) : 1 - 적중률 (1 - H)
  • 미스 패널티(Miss Penalty) : 캐시 미스가 발생했을 때, 주기억 장치에서 데이터를 가져오는데 걸리는 추가 시간 ($T_{main}$)

캐시 접근 시간 50ns, 주기억 장치 접근 시간 100ns 로 가정

  1. 적중률 90% 일 때 AMAT = (0.9 * 50ns) + (0.1 * 100ns) = 45ns + 10ns = 55ns
  2. 적중률 95% 일 때 AMAT = (0.95 * 50ns) + (0.05 * 100ns) = 47.5ns + 5ns = 52.5ns

기본적으로 주기억 장치 접근 시간보다 캐시 기억 장치 접근 시간이 빠르기 때문에 적중률이 높을수록 평균적인 기억 장치 접근 시간이 감소합니다.

이 기사는 저작권자의 CC BY-NC 4.0 라이센스를 따릅니다.