KAIST CS311 전산기조직 (Spring 2023) 교재: Computer Organization and Design: The Hardware/Software Interface (Patterson & Hennessy, MIPS Edition)
메모리 (Memory)
컴퓨터에서 데이터를 저장하고 읽는 핵심 구성 요소인 메모리의 구조와 용어를 살펴본다.
메모리 용어
메모리를 이해하기 위한 기본 용어를 먼저 정리하자.
- Height: Memory의 address 개수. 총 몇 개의 주소를 가지는지를 나타낸다.
- Width: 한 address에 저장되는 bit 크기 (= word size). 한 번에 읽거나 쓸 수 있는 데이터의 단위이다.
- Memory Array: Memory를 구성하는 2차원 배열 구조
- Memory Cell (Binary Storage Cell): 1-bit 데이터를 저장하는 최소 저장 단위
- Word Line: 특정 row를 activate시키는 signal 전송 경로. Decoder의 output이 word line을 통해 해당 row를 활성화한다.
- Bit Line: 활성화된 row의 cell이 보내는 데이터가 전송되는 경로. 여러 row가 하나의 bit line을 공유한다 (shared line).
Memory Array 기본 구조
========================
Word Line 0 ──→ ┌──────┬──────┬──────┬──────┐
│ Cell │ Cell │ Cell │ Cell │
Word Line 1 ──→ ├──────┼──────┼──────┼──────┤
│ Cell │ Cell │ Cell │ Cell │
Word Line 2 ──→ ├──────┼──────┼──────┼──────┤
│ Cell │ Cell │ Cell │ Cell │
Word Line 3 ──→ ├──────┼──────┼──────┼──────┤
│ Cell │ Cell │ Cell │ Cell │
└──┬───┴──┬───┴──┬───┴──┬───┘
│ │ │ │
Bit Bit Bit Bit
Line 0 Line 1 Line 2 Line 3
SRAM (Static RAM)
SRAM의 구조를 4M × 8 SRAM을 예시로 살펴보자. 4M(= 2²²)개의 address를 가지며, 각 address에 8-bit 데이터를 저장한다.
기본 구조
Memory의 width만큼 Memory Array와 MUX가 필요하다. 즉, 8-bit output을 위해 8개의 Memory Array와 8개의 MUX가 필요하다. 각 Memory Array + MUX 쌍이 output의 1-bit를 결정한다.
Two-Level Decode
하나의 거대한 decoder로 모든 address를 처리하면 비효율적이므로, two-level decode 방식을 사용한다.
- [4K × 1024 Memory Array] + [1024 × 1 MUX] 로 분할
- 상위 12-bit → word line (decoder의 input으로 사용, 4K = 2¹² 개의 row 선택)
- 하위 10-bit → bit line (MUX의 selection signal로 사용, 1024 = 2¹⁰ 개의 column 선택)
4M x 8 SRAM: Two-Level Decode (한 bit에 대한 구조)
====================================================
22-bit Address
┌─────────────┬──────────────┐
│ 상위 12-bit │ 하위 10-bit │
└──────┬──────┴──────┬───────┘
│ │
▼ │
┌───────────┐ │
│ Decoder │ │
│ (12-to- │ │
│ 4096) │ │
└─────┬─────┘ │
│ word line │
▼ │
┌──────────────────┐ │
│ 4K x 1024 │ │
│ Memory Array │ │
│ │ │
│ (4096 rows × │ │
│ 1024 columns) │ │
└────────┬─────────┘ │
│ 1024 │
│ bit lines │
▼ ▼
┌──────────────────┐
│ 1024-to-1 MUX │
│ (10-bit select) │
└────────┬─────────┘
│
▼
1-bit output
이 구조가 8개 병렬로 존재하여 최종 8-bit output을 만든다. 즉, 한 쌍의 Memory Array와 MUX는 output 8-bit 중 한 bit를 결정하는 역할을 한다.
DRAM (Dynamic RAM)
DRAM의 구조를 64M × 4 DRAM을 예시로 살펴보자. 64M(= 2²⁶)개의 address를 가지며, 각 address에 4-bit 데이터를 저장한다.
기본 구조
SRAM과 달리 DRAM은 단 하나의 거대한 Memory Array를 사용한다. 총 memory cell 수는 2²⁸개 (= 2²⁶ × 2² = 2²⁶ address × 4-bit)이다.
Address Pin 공유
DRAM은 비용(cost)을 줄이기 위해 row access와 column access에 사용되는 address 핀을 공유한다. 같은 address line을 시간차를 두고 두 번 사용하는 것이다.
- RAS (Row Address Strobe) = 1 → address line에 있는 address는 row access를 위한 것이므로 Row Decoder로 전달
- CAS (Column Address Strobe) = 1 → address line에 있는 address는 column access를 위한 것이므로 MUX로 전달
이를 통해 필요한 address 핀 수를 절반으로 줄일 수 있다.
Two-Level Decode
[2¹⁵ × 2¹³ Memory Array]를 사용한다고 가정하면:
- 26-bit 중 상위 15-bit → row access를 위해 Row Decoder의 input으로 사용
- 26-bit 중 하위 11-bit → column access를 위해 MUX의 selection signal로 사용
64M x 4 DRAM: Address Pin 공유 방식
=====================================
Address Line (공유)
┌──────────────────┐
│ address pins │
└────────┬─────────┘
│
┌─────┴─────┐
│ │
▼ ▼
┌──────┐ ┌──────┐
│ RAS │ │ CAS │
│ =1 │ │ =1 │
└──┬───┘ └──┬───┘
│ │
▼ │
┌────────┐ │
│ Row │ │
│Decoder │ │
└───┬────┘ │
│ │
▼ ▼
┌───────────────────────┐
│ 2^15 x 2^13 │
│ Memory Array │
│ │
│ (거대한 단일 배열) │
└───────────┬───────────┘
│
▼
┌───────────┐
│ MUX │
└─────┬─────┘
│
▼
4-bit output
Memory Array에서 row access가 끝나면, 2¹³ bit 데이터가 전송된다. 이 데이터는 4개로 분할되어 output의 각 bit(2¹¹ × 1 MUX)에 input으로 들어간다. 각 MUX는 11-bit의 selection signal로 데이터를 1 bit씩 뽑아내어, 최종적으로 4-bit output을 만든다.
2-Dimensional Address Decoding
Memory Array에 접근할 때 사용되는 2차원 주소 디코딩(2-Dimensional Address Decoding)에는 두 가지 방식이 있다.
Row Decoder & Column Decoder
- Row Selection과 Column Selection 모두 Decoder를 사용
- 두 Decoder의 activated line이 교차(intersection)하는 한 word (N개의 Memory Cell)를 Activate
- EE303에서 배운 메모리 방식
Row Decoder & Column Decoder 방식
==================================
Row Address ──→ ┌─────────┐
│ Row │──→ Word Line (row 선택)
│ Decoder │
└─────────┘
│
▼
┌───────────────┐
│ Memory Array │
└───────┬───────┘
│
Col Address ──→ ┌─────────┐
│ Column │──→ 교차점의 Cell Activate
│ Decoder │
└─────────┘
Row Decoder & Column MUX
- Row Selection에는 Decoder를 사용하고, Column Selection에는 MUX로 Bit Line 중 하나를 Select
- CS311에서 배운 방식
Row Decoder & Column MUX 방식
==============================
Row Address ──→ ┌─────────┐
│ Row │──→ Word Line (row 선택)
│ Decoder │
└─────────┘
│
▼
┌───────────────┐
│ Memory Array │
│ (전체 row의 │
│ bit line │
│ 데이터 출력) │
└───────┬───────┘
│ (다수의 bit lines)
▼
Col Address ──→ ┌─────────┐
│ Column │──→ 1-bit output
│ MUX │
└─────────┘
이 두 방식의 핵심 차이는 column 접근 시 Decoder를 쓰느냐, MUX를 쓰느냐이다. MUX 방식은 activated row의 모든 bit line 데이터를 받아서 그 중 하나를 선택하는 방식이다.
성능 평가 (Performance)
컴퓨터의 성능을 어떻게 정의하고 측정하는지 알아보자.
Performance Metrics (성능 지표)
컴퓨터 성능을 측정하는 두 가지 주요 지표가 있다:
- Response Time (Execution Time, 응답 시간): 어떤 task의 시작부터 종료까지 소요되는 시간. “작업이 얼마나 빨리 끝나는가?”
- Throughput (Bandwidth, 처리율): 단위 시간당 작업 처리량. “단위 시간에 얼마나 많은 작업을 처리하는가?”
Execution Time은 individual user에게 중요하고, Throughput은 server에게 중요하다.
성능(Performance)은 Execution Time의 역수로 정의한다:
Performance = 1 / Execution Time
Execution Time ↓ → Performance ↑
CPU Clocking
CPU는 clock signal에 의해 동기적으로 동작한다. 관련 용어를 정리하면:
- Clock Period (Clock Cycle Time): 하나의 clock cycle에 걸리는 시간. CC = 1 / CR (역수 관계)
- Clock Frequency (Clock Rate): 초당 clock cycle 수
- Cycle Time: 특정 연산이나 작업을 수행하는 데 걸리는 시간 (예: MemWrite = 50ns). 이 Cycle Time으로 특정 작업에 필요한 Clock Cycle 수를 알 수 있다 (예: MemWrite가 100 cycle 필요).
CPU Time
CPU가 어떤 task를 완료하는 데 소요되는 시간이 **CPU Execution Time (CPU Time)**이다.
CPU Time = [# Clock Cycle] × [Clock Cycle Time]
= [# Clock Cycle] / [Clock Rate]
여기서 # Clock Cycle은 프로그램이 실행되면서 필요한 총 Clock Cycle의 수이다.
이 공식을 더 세분화하면:
┌─────────────────────────────────────────────────────────┐
│ │
│ CPU Time = IC × CPI × CC │
│ │
│ IC = Instruction Count (명령어 개수) │
│ CPI = Cycles Per Instruction (명령어당 클럭 사이클 수) │
│ CC = Clock Cycle Time (클럭 주기) │
│ │
└─────────────────────────────────────────────────────────┘
Time Instructions Clock Cycles Seconds
────── = ──────────── × ──────────── × ──────────
Program Program Instruction Clock Cycle
CPU Time에 영향을 주는 요소들
CPU Time의 세 가지 구성 요소(IC, CPI, CC)는 각각 다른 계층에서 결정된다:
| 요소 | 영향을 주는 계층 |
|---|---|
| Instruction Count | Algorithm, Programming Language, Compiler, ISA |
| CPI | ISA, Core Organization (μArchitecture) |
| Clock Cycle | Core Organization, Transistor Technology |
- CPU Time: Execution Time으로 우리가 구하고자 하는 것. 직접 측정할 수 있다.
- Clock Cycle: 각 Clock Cycle당 소요되는 시간. CPU에 의해 주어질 수도 있다 (Clock Rate로).
- Instruction Count: software tool을 이용해 implementation detail 없는 재료 개선 기능. program(binary)에 의해 결정됨.
- CPI: implementation detail을 알아야 하고, instruction type과 ISA implementation에 의해 결정됨.
CPI (Cycles Per Instruction)
CPI는 **[# Clock Cycle] / [# Instruction]**으로, 명령어 하나를 실행하는 데 평균적으로 필요한 clock cycle 수이다.
따라서:
# Clock Cycle = # Instruction × CPI
하지만 실제로는 명령어의 종류에 따라 필요한 Clock Cycle 수가 다르다. 예를 들어 Load 명령어는 ALU 명령어보다 더 많은 cycle이 필요하다.
Effective CPI (유효 CPI)
각 명령어 class의 CPI를 전체 비율(portion)에 맞게 가중 평균하여 구한 CPI를 Effective CPI라 한다.
Effective CPI = Σ (CPI_i × F_i)
CPI_i = class i의 CPI
F_i = class i가 전체 명령어에서 차지하는 비율
CPI를 비교할 때는 같은 ISA와 같은 binary여야 의미 있는 비교가 가능하다.
Benchmark (벤치마크)
실제 컴퓨터 성능을 비교할 때는 벤치마크를 사용한다.
- Workload: 컴퓨터에서 실행하는 프로그램들의 세트 (a set of programs run on a computer)
- Benchmark: 성능 비교에 사용되는 Workload. 예) SPEC, SPECpower(전력), SPECmail(메일), mediabench(멀티미디어)
SPEC Ratio
SPEC ratio는 Execution Time의 **역수(inverse)**이다. 따라서 값이 클수록 더 빠른 컴퓨터임을 의미한다.
여러 벤치마크의 SPEC ratio를 하나의 성능 지표로 종합할 때는 **산술 평균이 아닌 기하 평균(Geometric Mean)**을 사용한다:
Performance = Geometric Mean of SPEC ratios
= ⁿ√(∏ SPEC_ratio_i)
기하 평균을 사용하는 이유는 비율(ratio) 값들의 평균으로 산술 평균이 적절하지 않기 때문이다.
Power (전력)
프로세서의 전력 소비는 다음 공식으로 나타낸다:
┌────────────────────────────────────────────┐
│ │
│ Power = Capacitive Load × V² × F │
│ │
│ Capacitive Load: 회로의 용량성 부하 │
│ V: 각 트랜지스터에 공급되는 전압 (Voltage) │
│ F: 동작 주파수 (Frequency = Clock Rate) │
│ │
└────────────────────────────────────────────┘
Power Wall (전력 장벽)
기술이 발전하면서 Voltage를 더 이상 줄이기 힘든 상황에 봉착했다. 또한 전력 소비로 인한 발열을 더 이상 효과적으로 제거하기도 어렵다. 이를 Power Wall이라 한다:
- Voltage를 더 줄일 수 없다 (We can’t reduce voltage further)
- 열을 더 제거할 수 없다 (We can’t remove more heat)
DVFS (Dynamic Voltage Frequency Scaling)
전력 절감을 위해 프로세서는 DVFS 기술을 사용한다. CPU load(처리해야 할 instructions)에 따라 Voltage와 Frequency를 동적으로 조절하는 것이다:
바쁠 때: V ↑, F ↑ (성능 우선)
한가할 때: V ↓, F ↓ (전력 절감)
Amdahl’s Law (암달의 법칙)
시스템의 일부를 개선했을 때 전체 성능이 얼마나 향상되는지를 정량적으로 나타내는 법칙이다.
┌──────────────────────────────────────────────────────┐
│ │
│ T_old │
│ T_new = T_affected / Improvement Factor │
│ + T_unaffected │
│ │
│ Speedup = T_old / T_new │
│ │
└──────────────────────────────────────────────────────┘
핵심은 개선하지 않은 부분이 전체 성능 향상의 상한을 결정한다는 것이다.
예시
어떤 작업에서 multiply가 전체의 80%를 차지한다고 하자. Multiply를 5배 빠르게 개선하면 전체 성능은?
T_old = 1 (정규화)
T_new = 0.8 / 5 + 0.2
= 0.16 + 0.2
= 0.36
Speedup = 1 / 0.36 ≈ 2.78배
만약 multiply를 아무리 빠르게 (∞배) 만들어도:
T_new = 0.8 / ∞ + 0.2
= 0 + 0.2
= 0.2
Speedup = 1 / 0.2 = 5배 (최대 한계!)
80%를 차지하는 부분을 아무리 개선해도 전체 성능은 최대 5배까지밖에 향상되지 않는다. 이것이 Amdahl’s Law의 핵심이다.
Corollary: Make the Common Case Fast
Amdahl’s Law의 당연한 귀결(corollary)은 **“자주 사용되는 경우(common case)를 빠르게 만들어라”**이다. 전체에서 큰 비중을 차지하는 부분을 개선해야 전체 성능 향상에 효과적이기 때문이다.
┌──────────────────────────────────────────────┐
│ │
│ Amdahl's Law의 교훈: │
│ │
│ 1. 전체의 큰 비율을 차지하는 부분을 개선하라 │
│ 2. 개선 불가능한 부분이 성능 상한을 결정한다 │
│ 3. 병렬화의 한계도 이 법칙으로 설명된다 │
│ │
└──────────────────────────────────────────────┘
정리
이번 글에서는 메모리 소자의 구조와 컴퓨터 성능 평가 방법을 살펴보았다.
메모리 부분에서는:
- Memory Array의 기본 용어 (height, width, word line, bit line)
- SRAM의 구조: width만큼의 Memory Array + MUX 쌍, two-level decode
- DRAM의 구조: 단일 거대 Memory Array, RAS/CAS를 이용한 address pin 공유
- 2-Dimensional Address Decoding의 두 가지 방식
성능 평가 부분에서는:
- Response Time vs Throughput
- CPU Time = IC × CPI × CC
- Effective CPI와 가중 평균
- Benchmark와 SPEC ratio (기하 평균)
- Power = Capacitive Load × V² × F, Power Wall, DVFS
- Amdahl’s Law: 부분 개선과 전체 성능의 관계
다음 글에서는 **ISA (Instruction Set Architecture)**에 대해 다루며, MIPS-32 ISA의 명령어 형식과 동작을 살펴볼 예정이다.