TL;DR
- 컴퓨터의 저장장치는 피라미드 구조로 되어 있다. 위로 갈수록 빠르고 작고 비싸고, 아래로 갈수록 느리고 크고 싸다.
- 각 레벨은 바로 아래 레벨의 일부 데이터를 복사해서 들고 있다. 이게 캐싱이다.
- CPU는 데이터가 필요하면 가까운 곳(레지스터)부터 찾는다. 없으면 아래로 내려간다.
- 캐시가 효과를 보는 이유는 프로그램이 지역성(locality)을 갖기 때문이다.
- - cache line, hit, miss, miss penalty
전체 구조도
┌─────────────┐
│ L0: Regs │ ← CPU 내부, 가장 빠름 (word 단위)
├─────────────┤
│ L1: Cache │ ← SRAM, cache line 단위
├─────────────┤
│ L2: Cache │
├─────────────┤
│ L3: Cache │
├─────────────┤
│ L4: DRAM │ ← 메인 메모리 (disk block 단위로 캐싱)
├─────────────┤
│ L5: SSD/HDD │ ← 로컬 디스크 (file 단위로 캐싱)
├─────────────┤
│ L6: Remote │ ← 원격 저장소 (네트워크)
└─────────────┘
↑ 위로 갈수록: Smaller, Faster, Costlier (per byte)
↓ 아래로 갈수록: Larger, Slower, Cheaper (per byte)
1. 왜 메모리 계층이 필요한가
CPU는 연산 자체는 엄청 빠르다. 문제는 데이터를 가져오는 속도다.
만약 CPU가 매번 느린 저장장치(DRAM, 디스크)까지 직접 갔다 오면, CPU가 계산을 끝내고도 데이터를 기다리는 시간이 발생한다.
- 병목(bottleneck)
그래서 CPU와 느린 저장장치 사이에 빠른 작은 저장소(캐시)를 끼워 넣는다. 자주 쓰는 데이터를 캐시에 올려두면, 대부분의 접근이 캐시에서 끝나서 평균 접근 시간이 확 줄어든다.
핵심 트레이드오프:
- 빠른 저장장치는 비싸고 작음
- 큰 저장장치는 싸지만 느림
- 둘 다 가질 수 없으니 계층 구조로 타협
2. 계층 구성과 각 레벨의 역할
레벨 이름 특징 데이터 단위 누가 관리하는지?
| L0 | Register (레지스터) | CPU 내부, 가장 빠름 | word | 하드웨어 + 컴파일러 |
| L1 | L1 Cache | CPU 코어에 붙어있음 | cache line | 하드웨어 |
| L2 | L2 Cache | L1보다 크고 약간 느림 | cache line | 하드웨어 |
| L3 | L3 Cache | 여러 코어가 공유하기도 함 | cache line | 하드웨어 |
| L4 | Main Memory (DRAM) | 우리가 말하는 RAM | disk block/page | OS |
| L5 | Local Disk (SSD/HDD) | 비휘발성, 영구 저장 | file | OS/파일시스템 |
| L6 | Remote Storage | 네트워크 너머 저장소 | file | 애플리케이션/OS |
register file의 "file"은 파일시스템의 파일이 아니라, 레지스터들의 집합/배열을 뜻하는 하드웨어 용어다.
3. 핵심 원리: 각 레벨이 아래 레벨을 캐싱한다
CSAPP 원문의 핵심 문장:
"The main idea of a memory hierarchy is that storage at one level serves as a cache for storage at the next lower level."
풀어서 말하면:
- 레지스터는 L1 캐시에서 가져온 값을 들고 있다
- L1 캐시는 L2에서 가져온 cache line을 들고 있다
- L3 캐시는 메인 메모리(DRAM)에서 가져온 cache line을 들고 있다
- DRAM은 디스크에서 가져온 disk block을 들고 있다
- 로컬 디스크는 원격 서버에서 가져온 file을 들고 있다
이게 "캐싱"이다. 아래에서 가져온 데이터의 복사본을 위에 올려두고, 다음에 필요하면 위부터 먼저 찾는다.
4. 캐싱(Caching)이란
헷갈리기 쉬운 포인트를 정리하면:
- 캐시(Cache): 하드웨어. 빠른 저장 공간 자체.
- 캐싱(Caching): 동작/전략. "복사해두고 먼저 찾는" 방식.
캐싱의 동작:
- 데이터가 필요하면 위 레벨부터 찾는다
- 있으면(hit) 바로 사용
- 없으면(miss) 아래 레벨에서 가져온다
- 가져온 데이터를 위 레벨에 복사해둔다
- 다음에 같은 데이터가 필요하면 hit로 빠르게 끝난다
5. 캐시가 효과를 보는 이유: 지역성 (Locality)
캐시가 작동하는 이유는 프로그램이 보통 지역성을 갖기 때문이다.
시간 지역성 (Temporal Locality)
방금 쓴 데이터를 곧 다시 쓴다.
for (int i = 0; i < 1000; i++) {
sum += arr[i]; // sum을 계속 반복해서 접근
}
sum 변수는 루프 내내 반복 접근된다. 한 번 캐시에 올라오면 계속 hit.
공간 지역성 (Spatial Locality)
어떤 주소를 쓰면 근처 주소도 곧 쓴다.
for (int i = 0; i < 1000; i++) {
sum += arr[i]; // arr[0], arr[1], arr[2]... 순서대로 접근
}
arr[0]을 읽을 때 arr[1], arr[2]도 같은 cache line에 들어있을 확률이 높다. 한 번 가져오면 근처 데이터도 같이 와서 다음 접근이 빨라진다.
이래서 캐시는 데이터를 한 바이트씩이 아니라 덩어리(cache line)로 가져온다.
6. 핵심 용어 정리
Cache Line (Block)
캐시가 데이터를 옮기는 덩어리 단위. 보통 64바이트 정도. 공간 지역성을 활용하기 위해 근처 데이터까지 한 번에 가져온다.
Hit
찾는 데이터가 현재 레벨에 있는 경우. 빠르다.
Miss
찾는 데이터가 현재 레벨에 없는 경우. 아래 레벨까지 가야 해서 느리다.
Miss Penalty
miss가 났을 때 아래 레벨까지 갔다 오는 추가 시간. 계층이 아래일수록 penalty가 크다.
Hit Time
hit일 때 데이터를 가져오는 시간.
Hit Rate / Miss Rate
전체 접근 중 hit/miss의 비율. hit rate가 높을수록 성능이 좋다.
7. 평균 접근 시간 (AMAT)
Average Memory Access Time의 줄임말이다.
AMAT = Hit Time + (Miss Rate × Miss Penalty)
의미: 평균적으로 데이터 하나 가져오는 데 걸리는 시간.
- Hit Time이 작을수록 좋다
- Miss Rate가 낮을수록 좋다
- Miss Penalty가 작을수록 좋다
결국 hit를 많이 만들면 평균 접근 시간이 줄어든다.
8. 자주 헷갈리는 포인트
"캐싱은 하드웨어만 하는 건가?"
아니다. L1~L3 캐시는 하드웨어가 자동 관리하지만, DRAM이 디스크를 캐싱하는 건 OS가 관리한다(page cache, buffer cache). 로컬 디스크가 원격을 캐싱하는 건 애플리케이션/OS 수준이다.
"캐시가 메모리인가?"
캐시는 메모리의 한 종류다. 정확히는 "CPU와 메인 메모리 사이에 있는 고속 메모리"다. 메인 메모리(DRAM)와 구분해서 말할 때는 "캐시"와 "메모리"를 따로 부르기도 한다.
- L0: 레지스터 (캐시라고 부르지 않음)
- L1~L3: 캐시 메모리 (SRAM)
- L4: 메인 메모리 (DRAM)
- L5~L6: 저장장치 (Storage)
"캐시"라고 부르는 건 보통 L1~L3이다.
"DRAM이 디스크의 캐시라는 게 어떤 의미인가?"
OS가 파일을 읽으면 디스크에서 가져온 내용을 DRAM에 남겨둔다(page cache). 같은 파일을 다시 읽으면 디스크까지 안 가고 DRAM에서 바로 준다. 이런 의미에서 "DRAM이 디스크를 캐싱한다"고 말한다.
9. 용어 사전
| Memory Hierarchy | 메모리 계층 | 저장장치를 속도/용량/비용 기준으로 층층이 구성한 구조 |
| Register | 레지스터 | CPU 내부의 가장 빠른 저장공간 |
| Register File | 레지스터 파일 | 레지스터들의 집합/배열 (하드웨어 용어) |
| Cache | 캐시 | CPU와 메인 메모리 사이의 고속 메모리 |
| Cache Line | 캐시 라인 | 캐시가 데이터를 옮기는 덩어리 단위 (보통 64B) |
| SRAM | 정적 램 | 캐시에 쓰이는 빠른 메모리 |
| DRAM | 동적 램 | 메인 메모리에 쓰이는 메모리 |
| Main Memory | 메인 메모리 | 실행 중인 프로그램의 작업 공간 (RAM) |
| Hit | 히트 | 찾는 데이터가 현재 레벨에 있는 경우 |
| Miss | 미스 | 찾는 데이터가 현재 레벨에 없는 경우 |
| Miss Penalty | 미스 패널티 | miss 시 아래 레벨까지 가는 추가 시간 |
| Hit Rate | 히트율 | 전체 접근 중 hit의 비율 |
| Locality | 지역성 | 프로그램이 특정 데이터/주소에 집중 접근하는 특성 |
| Temporal Locality | 시간 지역성 | 방금 쓴 데이터를 곧 다시 쓰는 특성 |
| Spatial Locality | 공간 지역성 | 어떤 주소를 쓰면 근처도 곧 쓰는 특성 |
| Bottleneck | 병목 | 전체 속도를 제한하는 가장 느린 구간 |
| Processor / CPU | 프로세서 | 명령을 실행하는 연산 장치 |
| Word | 워드 | CPU가 한 번에 다루는 기본 데이터 크기 |
| Block | 블록 | 저장장치 간 데이터 이동 단위 (= cache line과 비슷한 개념) |
| Page Cache | 페이지 캐시 | OS가 DRAM에 유지하는 디스크 데이터 복사본 |
| SSD | solid state drive | 플래시 메모리 기반 저장장치 |
| HDD | hard disk drive | 자기 디스크 기반 저장장치 |
10. 체크리스트
- [ ] 메모리 계층에서 위로 갈수록 어떤 특성이 있는지 말할 수 있다
- [ ] L0~L6이 각각 뭔지 한 줄로 설명할 수 있다
- [ ] "각 레벨이 아래 레벨을 캐싱한다"는 말의 의미를 안다
- [ ] cache line이 뭔지, 왜 덩어리로 가져오는지 안다
- [ ] hit와 miss의 차이를 안다
- [ ] 시간 지역성과 공간 지역성을 예시와 함께 설명할 수 있다
- [ ] "캐시"와 "캐싱"의 차이를 안다
- [ ] DRAM이 디스크의 캐시라는 말이 무슨 뜻인지 안다
'concept' 카테고리의 다른 글
| Google Dev Challenge: C 언어 타입 변환의 함정 (1) | 2025.11.25 |
|---|---|
| [OS] 뮤텍스 + Block() 방식의 문제점 (Producer-Consumer Problem) (0) | 2025.11.17 |
| [운영체제론] Constant Time Coalescing (Case 1-4) 정리 (0) | 2025.11.08 |
| tmux (수정 예정) (0) | 2025.11.03 |
| [운영체제론] 가상 메모리 (0) | 2025.10.31 |