실행 중인 프로그램은 메모리에 저장되며, CPU는 메모리에 저장된 정보를 읽고, 쓰고, 실행함
메인 메모리를 구성하는 하드웨어에는 RAM과 ROM이 있지만, 일반적으로 메모리(RAM)를 의미하는 경우가 많음
CPU는 보조기억장치에 저장된 프로그램을 직접 실행할 수 없기 때문에, 프로그램을 실행하려면 보조기억장치에서 RAM으로 데이터를 복사해야 함. 따라서 RAM의 용량은 컴퓨터 성능에 큰 영향을 미치게 됨
: Random Access Memory(임의 접근 메모리)의 약자로, 임의의 위치에 곧장 접근할 수 있는 방식을 의미
이러한 특성 때문에 RAM은 CPU가 빠르게 데이터를 읽고 실행할 수 있도록 도와주는 중요한 역할을 함

: RAM은 크게 DRAM, SRAM, SDRAM, DDR SDRAM 등으로 나뉨
1️⃣ DRAM
2️⃣ SRAM
3️⃣ SDRAM
4️⃣ DDR SDRAM
> 한 클럭당 하나씩 데이터를 주고받을 수 있는 SDRAM은 SDR SDRAM(Single Data Rate SDRAM)이라고 부르기도 함
> 대역폭: 데이터를 주고받을 길의 너비
⏹️ DDR SDRAM의 발전
DDR2 SDRAM → DDR SDRAM보다 대역폭이 2배 증가 (SDR SDRAM보다 4배 넓은 대역폭)
DDR3 SDRAM → DDR2 SDRAM보다 대역폭이 2배 증가 (SDR SDRAM보다 8배 넓은 대역폭)
DDR4 SDRAM → 최근 가장 흔히 사용되며, SDR SDRAM보다 16배 넓은 대역폭을 제공

현대의 메모리는 데이터를 바이트 단위로 저장하고 관리하지만, CPU는 바이트 단위가 아니라 4바이트(32비트) 또는 8바이트(64비트) 단위(워드 단위)로 데이터를 처리 함
따라서, 여러 바이트로 구성된 데이터는 여러 개의 주소에 나누어 저장됨
4바이트 데이터(32비트) → 4개의 주소에 저장
8바이트 데이터(64비트) → 8개의 주소에 저장
16진수 1A2B3C4D → 1A, 2B, 3C, 4D 로 나누어 4개의 주소에 저장
16진수 1A2B3C4D5A6B7C8D → 1A, 2B, 3C, 4D, 5A, 6B, 7C, 8D 로 나누어 8개의 주소에 저장
데이터를 여러 개의 주소에 저장할 때, 어떤 순서로 저장하느냐에 따라 엔디안이 달라짐
마치 언어에서 글을 왼쪽에서 오른쪽으로 읽거나, 오른쪽에서 왼쪽으로 읽는 문화 차이가 있는 것과 비슷함
⏹️ 빅 엔디안 (Big Endian)

⏹️ 리틀 엔디안 (Little Endian)

MSB / LSB
MSB(Most Significant Bit): 숫자의 크기에 가장 큰 영향을 미치는 가장 왼쪽 비트
LSB(Least Significant Bit): 숫자의 크기에 가장 적은 영향을 미치는 가장 오른쪽 비트
- 10진수 123 → MSB: 1, LSB: 3
⏹️ 빅 엔디안 (Big Endian)
⏹️ 리틀 엔디안 (Little Endian)
> 바이 엔디안 (Bi-Endian)
일부 컴퓨터 환경에서는 빅 엔디안과 리틀 엔디안을 선택 가능하도록 설계
한 줄 정리
빅 엔디안 → 사람이 읽기 쉬움
리틀 엔디안 → 컴퓨터 연산이 효율적
10진수 107.6640625는 16진수로 42D75400 으로 변환된다.
⏹️ 빅 엔디안 (Big Endian) 표현
⏹️ 리틀 엔디안 (Little Endian) 표현

CPU의 연산 속도와 메모리 접근 속도의 차이를 줄이기 위해 도입된 SRAM 기반의 저장 장치
CPU가 메모리에 자주 접근하는 시간을 단축하기 위해, 필요한 데이터를 미리 캐시 메모리에 저장하여 활용

1️⃣ L1 캐시 (Level 1 Cache)


2️⃣ L2 캐시 (Level 2 Cache)
3️⃣ L3 캐시 (Level 3 Cache)
⏹️ 속도와 크기 비교
속도: L1 > L2 > L3
크기: L1 < L2 < L3
캐시 메모리는 CPU와 메모리 간 속도 차이를 줄이는 필수적인 중간 저장소로, 속도와 용량이 다른 계층적 구조(L1, L2, L3)를 통해 CPU 성능을 최적화
캐시 메모리에 저장되는 데이터
- 캐시 메모리는 용량이 작아 메모리의 모든 데이터를 저장할 수 없음
- CPU가 사용할 법한 것을 저장
보조저장장치는 (전원이 꺼져도)'보관할 것'을 저장하고
메모리는 '실행 중인 것'을 저장
캐시 히트(Cache Hit):
- 캐시 메모리가 예측한 데이터가 CPU에 의해 실제로 사용되는 경우
- CPU는 캐시 메모리에서 데이터를 빠르게 가져올 수 있음
캐시 미스(Cache Miss):
- 캐시 메모리에 데이터가 없거나 잘못된 예측으로 CPU가 메모리에서 직접 데이터를 가져와야 하는 경우
- 캐시 미스가 발생하면 캐시 메모리의 이점을 활용할 수 없어 CPU 성능이 떨어짐
캐시 적중률(Cache Hit Ratio):
- 캐시 적중률은 캐시가 히트된 비율을 나타내는 지표
- 범용 컴퓨터의 캐시 적중률은 85% ~ 95% 이상으로 높은 편
캐시 메모리는 CPU가 사용할 가능성이 높은 데이터를 저장해 성능을 최적화하며, 캐시 히트율이 높을수록 CPU 성능이 극대화 됨
캐시 메모리는 참조 지역성의 원리라는 특정한 원칙에 따라 메모리부터 가져올 데이터를 결정
시간 지역성 (Temporal Locality)
CPU는 최근에 접근한 메모리 공간에 다시 접근하려는 경향이 있음
예: 프로그램 변수는 한 번만 사용되지 않고 여러 번 참조되므로, 최근 사용된 데이터가 다시 사용될 가능성이 높음
공간 지역성 (Spatial Locality)
CPU는 현재 접근한 메모리 공간 근처의 데이터를 접근하려는 경향이 있음
예: 배열처럼 연속된 메모리 공간에 저장된 데이터에 접근 시, 근처 데이터를 연속적으로 참조할 가능성이 큼
두 가지 코드(locality_good.py, locality_bad.py)를 비교
# locality_good.py
matrix = [[0] * 20000 for _ in range(20000)] # 2만 x 2만 크기의 2차원 배열 생성
for i in range(20000): # i를 0부터 19999까지 반복
for j in range(20000): # j를 0부터 19999까지 반복
matrix[i][j] = 1 # matrix[i][j]를 1로 갱싱
# locality_bad.py
matrix = [[0] * 20000 for _ in range(20000)] # 2만 x 2만 크기의 2차원 배열 생성
for i in range(20000): # i를 0부터 19999까지 반복
for j in range(20000): # j를 0부터 19999까지 반복
matrix[j][i] = 1 # matrix[j][i]를 1로 갱싱
locality_good.py (공간 지역성 O)
- 2차원 배열에 접근 시, 행(row) 단위로 순차적으로 접근
- 메모리 배열에 저장된 순서와 동일하게 데이터를 참조하므로 캐시 메모리 적중률이 높음
locality_bad.py (공간 지역성 X)
- 2차원 배열에 접근 시, 열(column) 단위로 접근
- 메모리 내 데이터가 비순차적으로 참조되어 캐시 메모리 적중률이 낮음
2차원 배열 메모리 저장 구조
메모리는 2차원 배열을 일렬로 저장
예) 4x4 배열:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
[13, 14, 15, 16]
→ 메모리 저장 순서: 1, 2, 3, ..., 16

캐시 메모리를 효과적으로 활용하려면 참조 지역성을 고려한 코드를 작성해야 한다.
시간 지역성 → 최근 사용된 데이터를 재사용
공간 지역성 → 연속된 데이터 접근 패턴 유지
CPU가 캐시 메모리에 데이터를 쓸 때는 캐시 메모리에 새롭게 쓰여진 데이터와 메모리 상의 데이터가 일관성을 유지해야 함

데이터 일관성이 깨지면 예상치 못한 결과가 나타날 수 있음
1️⃣ 즉시 쓰기 (Write-Through)

2️⃣ 지연 쓰기 (Write-Back)

캐싱은 성능을 높이지만, 데이터의 원본과 캐시 간 불일치 문제를 해결해야 한다.
참고: 북스터디 - 이것이 취업을 위한 컴퓨터 과학이다 (Chapter 2-4)