[CS] 메모리(RAM, 엔디안, 캐시 메모리)

눈치없어·2025년 2월 4일

실행 중인 프로그램은 메모리에 저장되며, CPU는 메모리에 저장된 정보를 읽고, 쓰고, 실행함


RAM

메인 메모리를 구성하는 하드웨어에는 RAM과 ROM이 있지만, 일반적으로 메모리(RAM)를 의미하는 경우가 많음

CPU는 보조기억장치에 저장된 프로그램을 직접 실행할 수 없기 때문에, 프로그램을 실행하려면 보조기억장치에서 RAM으로 데이터를 복사해야 함. 따라서 RAM의 용량은 컴퓨터 성능에 큰 영향을 미치게 됨

  • RAM 용량이 작으면, 실행할 프로그램을 자주 보조기억장치에서 불러와야 하므로 실행 속도가 느려짐
  • 반대로, RAM 용량이 충분하면 더 많은 데이터를 한 번에 로드하여 저장할 수 있으므로 여러 프로그램을 원활하게 실행할 수 있음
  • 하지만, RAM이 필요 이상으로 크다고 해서 반드시 성능이 비례하여 향상되는 것은 아님

📌 RAM의 의미

: Random Access Memory(임의 접근 메모리)의 약자로, 임의의 위치에 곧장 접근할 수 있는 방식을 의미

  • 임의 접근(Random Access):
    - 데이터를 저장한 위치에 순차적으로 접근할 필요 없이 원하는 주소로 즉시 접근할 수 있는 방식(직접 접근이라고도 함)
    - 예를 들어, 100번지의 데이터에 접근하려면 1번지부터 차례로 접근하는 것이 아니라 곧장 100번지로 이동할 수 있음
    - 따라서, 어떤 위치의 데이터에 접근하든 속도가 동일
  • 순차 접근(Sequential Access)과의 차이
    - 순차 접근 방식은 데이터를 처음부터 차례로 읽어야만 원하는 위치에 도달할 수 있음
    - 이 방식에서는 접근하려는 위치에 따라 소요 시간이 달라질 수 있음

이러한 특성 때문에 RAM은 CPU가 빠르게 데이터를 읽고 실행할 수 있도록 도와주는 중요한 역할을 함



📌 RAM의 종류

: RAM은 크게 DRAM, SRAM, SDRAM, DDR SDRAM 등으로 나뉨

1️⃣ DRAM

  • Dynamic(동적) RAM이라는 이름 그대로, 저장된 데이터가 시간이 지나면서 점차 사라지는 특성
  • 데이터의 소멸을 막기 위해 일정 주기로 재활성화(다시 저장) 작업이 필요함
  • 하지만, 소비 전력이 낮고, 가격이 저렴하며, 집적도가 높아 대용량 메모리 설계에 유리함

2️⃣ SRAM

  • Static(정적) RAM은 DRAM과 달리, 저장된 데이터가 일정 시간 동안 유지되는 RAM
  • 단, 전원이 차단되면 데이터가 소멸된다는 점에서 비휘발성 저장장치는 아님
  • DRAM보다 속도가 빠르지만, 소비 전력이 크고, 가격이 비싸며, 집적도가 낮음
  • 대용량으로 설계하기에는 부담이 크기 때문에, 속도가 중요한 캐시 메모리 등에 사용

3️⃣ SDRAM

  • 클럭 신호와 동기화된, 보다 발전된 형태의 DRAM
  • 클럭 타이밍에 맞춰 CPU와 정보를 주고받을 수 있도록 설계됨

4️⃣ DDR SDRAM

  • 대역폭을 넓혀 속도를 향상시킨 SDRAM
  • SDRAM이 한 클럭당 한 번씩 CPU와 데이터를 주고받는다면,
  • DDR SDRAM은 한 클럭당 두 번씩 데이터를 전송하여 속도를 두 배 높힘
  • 너비가 두 배인 자동차 도로와 같음
  • 한 클럭당 하나씩 데이터를 주고받을 수 있는 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개의 주소에 저장

📌 엔디안(Endianness) – 바이트 저장 순서

데이터를 여러 개의 주소에 저장할 때, 어떤 순서로 저장하느냐에 따라 엔디안이 달라짐
마치 언어에서 글을 왼쪽에서 오른쪽으로 읽거나, 오른쪽에서 왼쪽으로 읽는 문화 차이가 있는 것과 비슷함

⏹️ 빅 엔디안 (Big Endian)

  • 낮은 번지의 주소에 상위 바이트부터 저장하는 방식

⏹️ 리틀 엔디안 (Little Endian)

  • 낮은 번지의 주소에 하위 바이트부터 저장하는 방식

MSB / LSB
MSB(Most Significant Bit): 숫자의 크기에 가장 큰 영향을 미치는 가장 왼쪽 비트
LSB(Least Significant Bit): 숫자의 크기에 가장 적은 영향을 미치는 가장 오른쪽 비트

  • 10진수 123 → MSB: 1, LSB: 3

📌 빅 엔디안 / 리틀 엔디안 – 장단점 비교

⏹️ 빅 엔디안 (Big Endian)

  • 숫자를 읽고 쓰는 순서가 우리가 일상적으로 사용하는 방식과 동일
  • 메모리 값을 직접 읽거나 디버깅할 때 편리
  • 예) 주소에 1A, 2D, 3C, 4D의 순서대로 저장된 값 그대로 1A2D3C4D로 해석 가능

⏹️ 리틀 엔디안 (Little Endian)

  • 메모리 값을 직접 읽기는 어렵지만, 수치 계산에 유리
  • 예) 123 + 456에서 3과 6부터 연산하는 방식과 일치
> 바이 엔디안 (Bi-Endian)
일부 컴퓨터 환경에서는 빅 엔디안과 리틀 엔디안을 선택 가능하도록 설계

한 줄 정리
빅 엔디안 → 사람이 읽기 쉬움
리틀 엔디안 → 컴퓨터 연산이 효율적


📌 10진수 소수의 엔디안 표현

10진수 107.6640625는 16진수로 42D75400 으로 변환된다.

⏹️ 빅 엔디안 (Big Endian) 표현

  • 107.6640625를 16진수로 변환한 값은 42D75400
  • 빅 엔디안 방식에서는 그대로 메모리에 42D75400 이 저장됨

⏹️ 리틀 엔디안 (Little Endian) 표현

  • 같은 값(107.6640625)을 리틀 엔디안 방식으로 저장하면 0054D742
  • 저장되는 순서가 뒤집혀 42D75400 → 0054D742로 저장됨




캐시 메모리

CPU의 연산 속도와 메모리 접근 속도의 차이를 줄이기 위해 도입된 SRAM 기반의 저장 장치

CPU가 메모리에 자주 접근하는 시간을 단축하기 위해, 필요한 데이터를 미리 캐시 메모리에 저장하여 활용

📌 캐시 메모리를 사용하는 이유

  • CPU의 연산 속도는 매우 빠르지만, 메모리에 접근하는 속도는 상대적으로 느림
  • CPU가 메모리에 직접 접근하지 않고, 캐시 메모리를 통해 필요한 데이터를 미리 준비하면 연산 속도가 향상


📌 캐시 메모리의 계층 구조

1️⃣ L1 캐시 (Level 1 Cache)

  • 코어 내부에 위치
  • 가장 빠르지만 용량이 작음
  • 주로 명령어(L1I)데이터(L1D)를 따로 저장 (분리형 캐시)


2️⃣ L2 캐시 (Level 2 Cache)

  • 코어 내부 또는 외부에 위치
  • L1 캐시보다 용량이 크지만 속도가 느림

3️⃣ L3 캐시 (Level 3 Cache)

  • 코어 외부에 위치하며, 여러 코어가 공유
  • L2 캐시보다 용량이 크지만 속도가 더 느림

⏹️ 속도와 크기 비교
속도: L1 > L2 > L3
크기: L1 < L2 < L3

캐시 메모리는 CPU와 메모리 간 속도 차이를 줄이는 필수적인 중간 저장소로, 속도와 용량이 다른 계층적 구조(L1, L2, L3)를 통해 CPU 성능을 최적화


캐시 히트 / 캐시 미스

📌 캐시 메모리의 역할과 캐시 히트(Cache Hit)

  • 캐시 메모리에 저장되는 데이터
    - 캐시 메모리는 용량이 작아 메모리의 모든 데이터를 저장할 수 없음
    - 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가 캐시 메모리에 데이터를 쓸 때는 캐시 메모리에 새롭게 쓰여진 데이터와 메모리 상의 데이터가 일관성을 유지해야 함

📌 캐시 메모리와 메모리 데이터의 일관성 문제

  • 메모리와 캐시 메모리에 동일한 데이터(1000번지 값)가 저장되어 있다고 가정
  • CPU가 캐시 메모리를 통해 값을 200 → 300으로 수정한 경우, 메모리와 캐시 메모리 간 값이 불일치 발생 가능

데이터 일관성이 깨지면 예상치 못한 결과가 나타날 수 있음


📌 캐시 메모리에 데이터를 쓰는 두 가지 방법

1️⃣ 즉시 쓰기 (Write-Through)

  • 데이터를 캐시와 메모리에 동시에 저장
  • 장점:
    - 메모리와 캐시 메모리 간의 데이터 일관성 유지
    - 메모리를 항상 최신 상태로 유지
  • 단점:
    - 데이터를 쓸 때마다 메모리를 참조 → 쓰기 시간이 길어짐
    - 캐시 메모리의 효율 감소

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

  • 데이터를 캐시에만 저장하고, 나중에 메모리에 반영
  • 장점:
    - 메모리 접근 횟수 감소 → 쓰기 속도 빠름
  • 단점:
    - 메모리와 캐시 메모리 간 데이터 불일치 발생 가능
    - 데이터 일관성을 유지하기 위한 추가 처리 필요

캐싱은 성능을 높이지만, 데이터의 원본과 캐시 간 불일치 문제를 해결해야 한다.



참고: 북스터디 - 이것이 취업을 위한 컴퓨터 과학이다 (Chapter 2-4)

profile
dock 사이즈 다르잖아

0개의 댓글