CPU 파이프라인 분석 — 5-stage·Cortex-M·Cortex-A 비교
#한 줄 요약
Pipeline은 명령어 병렬화입니다. 한 사이클당 한 명령어 완료가 목표입니다.
#5-Stage Classic Pipeline (MIPS R3000)
| Stage | 작업 |
|---|---|
| F (Fetch) | PC가 가리키는 memory에서 명령어를 읽습니다 |
| D (Decode) | opcode를 해독하고 register를 read합니다 |
| E (Execute) | ALU 연산을 수행합니다 |
| M (Memory) | load/store 시 메모리에 액세스합니다 |
| W (Writeback) | register file에 결과를 씁니다 |
Time: 1 2 3 4 5 6 7 8Inst1: [F] [D] [E] [M] [W]Inst2: [F] [D] [E] [M] [W]Inst3: [F] [D] [E] [M] [W]Inst4: [F] [D] [E] [M] [W]이상적으로는 매 cycle마다 1 명령이 완료됩니다 (IPC = 1.0).
실제로는 데이터 의존성 때문에 stall이 발생합니다. 다음은 RAW(Read-After-Write) hazard 하나로 뒤따르는 명령들이 한 cycle씩 밀리는 모습입니다.
#Cortex-M0/M0+ — 2-Stage
[Fetch] → [Execute (Decode+Execute+WB 통합)]매우 단순한 구조라서 작은 die와 낮은 전력이 특징입니다. 분기 시 1 cycle을 손실합니다.
#Cortex-M3/M4 — 3-Stage
[Fetch] → [Decode] → [Execute (E+M+W 통합)]ldr r0, [r1] ; F D Eadd r2, r0, r3 ; F D E ← r0 사용r0 의존성이 있지만 load 결과가 같은 cycle에 ALU로 전달됩니다 (forwarding). Stall 없이 진행됩니다.
#Cortex-M7 — 6-Stage Dual-Issue
F1 → F2 → D → I → E1 → E2- F1·F2는 분리된 fetch입니다 (캐시 line 단위).
- D·I는 Decode와 Issue를 합칩니다 (2 instruction 동시).
- E1·E2는 ALU와 2nd ALU 또는 Load Store입니다.
Dual-issue로 IPC > 1이 가능합니다 (이론적으로 2.0).
#Cortex-A53 — 8-Stage In-Order
F1 F2 F3 D1 D2 I E1 E2In-order 발행에 dual-issue를 더한 구조입니다. 적당한 성능과 낮은 전력이 특징이며, Raspberry Pi 3B의 BCM2837에 들어 있습니다.
#Cortex-A72 — 15-Stage Out-of-Order
F1 F2 F3 F4 F5 D1 D2 D3 Dispatch [Issue Queue] ↓ [Multiple Execution Units] ↓ [Reorder Buffer] ↓ Commit- 5-stage fetch로 깊은 branch prediction을 지원합니다.
- Out-of-order issue로 의존성이 없는 명령을 먼저 실행합니다.
- 4-wide superscalar로 동시에 4 명령을 처리합니다.
성능이 높지만 전력 소모도 그만큼 큽니다.
#Pipeline 길이 Trade-off
| 길이 | 장점 | 단점 |
|---|---|---|
| 짧음 (3) | Branch miss penalty가 작습니다 | 클럭 속도 한계가 있습니다 |
| 중간 (8) | 균형이 잡힙니다 | — |
| 김 (15+) | 고클럭이 가능합니다 (1.5 GHz↑) | Mispredict penalty가 큽니다 |
Pentium 4는 31 stage였습니다. mispredict 시 31 cycle을 손실했고, 결국 실패한 디자인이 되었습니다.
#Throughput vs Latency
N=1000이면 pipeline은 200x throughput을 냅니다. 다만 latency (한 명령의 완료 시간)는 동일하거나 길어집니다.
#Pipeline Hazard 3종
#1. Structural Hazard
같은 hardware 자원을 두 명령이 동시에 사용하는 경우입니다. 예를 들어 단일 memory port에 F와 M이 동시 액세스하는 상황입니다.
해결책은 Harvard architecture입니다 (I-cache와 D-cache 분리).
#2. Data Hazard
add r0, r1, r2 ; r0 = r1 + r2sub r3, r0, r4 ; r0 사용 — 앞 명령 결과 필요add의 W 단계가 끝나기 전에 sub이 r0를 읽으려 합니다. forwarding이나 stall로 해결합니다.
#3. Control Hazard
beq r0, r1, label ; 분기 — 어디로 갈지 D 단계 후에야 알 수 있음add r2, r3, r4 ; ← 미리 fetch했지만 분기 시 무효branch prediction으로 해결합니다 (다음 편에서 다룹니다).
#ARM Forwarding (Cortex-M4)
ldr r0, [r1] ; F D E M W (load 완료 = W)mul r2, r0, r3 ; F D D' E M W ← stall 1 cycle (load-use)Load 결과는 forwarding이 불가능하여 1 cycle bubble이 생깁니다. 컴파일러가 재정렬을 시도합니다.
ldr r0, [r1] ; F D E M Wnop ; bubble 채움 (또는 독립 명령)mul r2, r0, r3#측정 — Cortex-M7 IPC
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;uint32_t start = DWT->CYCCNT;loop_kernel();uint32_t cycles = DWT->CYCCNT - start;
uint32_t insts = count_instructions_in_loop();float ipc = (float)insts / cycles;목표 IPC는 다음과 같습니다.
- Cortex-M0: ~0.7
- Cortex-M3: ~0.9
- Cortex-M4: ~0.95
- Cortex-M7 (dual-issue): ~1.5
- Cortex-A72 (OoO): ~3.0
#SuperH vs ARM Pipeline 차이
| ARM | SuperH SH-2/4 |
|---|---|
| Load delay slot이 묵시적입니다 | Delay slot이 명시적입니다 (branch 후 명령 항상 실행) |
| Conditional execution (Thumb-2)이 있습니다 | 없습니다 |
| 32 register | 16 register |
옛 자동차 ECU의 SH-4는 delay slot이 명시적이라 컴파일러가 명시적으로 처리해야 했습니다.
#자주 하는 실수
⚠️ Pipeline 깊이가 성능과 같지는 않음
Cortex-M7 6-stage가 Cortex-M3 3-stage보다 클럭당 더 빠른 건 아닙니다. Dual-issue를 활용했을 때만 그렇습니다.
⚠️ NOP으로 stall 해결 시도
ldr r0, [r1]nopnopadd r2, r0, r3컴파일러가 이미 더 잘 최적화합니다. 직접 NOP을 삽입하는 것은 보통 비최적입니다.
⚠️ 짧은 함수가 빠르다고 가정
함수 호출은 pipeline flush 가능성이 있습니다. 인라인이 더 빠릅니다. inline이나 LTO로 컴파일러를 도와줍니다.
⚠️ Cycle 측정 오류
DWT CYCCNT는 DMB와 DSB 없이는 정확하게 측정되지 않습니다. barrier를 추가합니다.
__DSB();uint32_t start = DWT->CYCCNT;/* code */__DSB();uint32_t end = DWT->CYCCNT;#정리
- Pipeline은 명령어 단계별 병렬화입니다 (F·D·E·M·W).
- Cortex-M0는 2-stage, M3/M4는 3-stage, M7은 6-stage dual-issue입니다.
- Cortex-A는 8~15-stage의 out-of-order superscalar입니다.
- 3 hazard (structural·data·control)는 forwarding과 branch prediction으로 회피합니다.
- Pipeline 깊이는 trade-off가 있습니다. 길수록 클럭이 높아지지만 mispredict 비용도 커집니다.
다음 편은 Pipeline Stall입니다. Data dependency를 자세히 다룹니다.
#관련 항목
Embedded Performance Engineering · 10 of 57
- 1Embedded Performance Engineering — 임베디드 성능 엔지니어링 시리즈 소개
- 2임베디드 성능 분석 방법론 — Measure → Analyze → Optimize 사이클
- 3성능 지표 정의 — Latency·Throughput·Utilization 분석
- 4성능 측정의 기본 — Wall-Clock·CPU Cycle·Instruction Count
- 5성능 데이터 통계적 분석 — Percentile·Histogram·평균의 함정
- 6실시간 성능 분석 — WCET·Jitter·Deadline Miss 측정
- 7임베디드 벤치마킹 기초 — 재현성·Warmup·노이즈 제거
- 8성능 모델링 — Amdahl·Gustafson·Roofline Model 적용
- 9프로파일링 기법 개요 — Sampling vs Instrumentation·PGO·LTO
- 10CPU 파이프라인 분석 — 5-stage·Cortex-M·Cortex-A 비교
- 11Pipeline Stall 분석 — Data·Structural·Control Hazard·Forwarding
- 12Branch Prediction 분석 — Static·2-bit·BTB·BHT·Mispredict 비용
- 13Speculative Execution 분석 — OoO·Reorder Buffer·Register Renaming
- 14CPU Cache 기초 — L1·L2·L3·Set Associative·Replacement Policy
- 15Cache Miss 3C Model 분석 — Compulsory·Capacity·Conflict
- 16Cache Line 최적화 — Alignment·Prefetch·False Sharing 처리
- 17메모리 대역폭 분석 — STREAM·Roofline·Bus Saturation 측정
- 18SIMD·NEON 활용 — 128-bit Vector·Auto-Vectorization·SVE/SVE2
- 19PMU·HPM 하드웨어 카운터 분석 — 정밀 성능 진단
- 20임베디드 Bus Architecture — AHB·AXI·CHI 진화와 5-Channel
- 21Bus Contention 진단 — Arbitration·QoS·Starvation 측정
- 22DMA 성능 최적화 — Burst·Scatter-Gather·Chain·Cache 일관성
- 23DMA vs CPU Copy 성능 비교 — Break-even·Setup Overhead 실측
- 24Interrupt Latency 분석 — 진입·종료·Tail-Chaining·Late Arrival
- 25Interrupt Storm 처리 — NAPI·Rate-Limit·Polling 전환
- 26MMIO 접근 성능 — Cache Policy·Write-Combining·Volatile·Barrier
- 27Peripheral Clock 분석 — PLL·Divider·Gating·DVFS
- 28Power vs Performance 트레이드오프 — DVFS·Race-to-Idle·Big.LITTLE
- 29Thermal Throttling 분석 — Junction Temp·Trip Point·냉각
- 30CXL Interconnect 분석 — AI 시대 메모리 대역폭 확장
- 31Concurrency 기초 — Concurrency vs Parallelism·Race·Memory Model
- 32False Sharing 진단 — Cache Line Ping-Pong·Padding·측정
- 33Lock Contention 분석 — Wait·Hold·Convoy·측정 기법
- 34Spinlock 성능 분석 — Spin-Wait vs Context Switch·Ticket·MCS
- 35Mutex 성능 분석 — Futex·Adaptive·Priority Inheritance
- 36Reader-Writer Lock 성능 — Reader/Writer Priority·RCU·Seqlock
- 37Lock-Free 자료구조 성능 — CAS·ABA·Hazard Pointer·Epoch Reclamation
- 38Memory Ordering 분석 — Acquire·Release·Seq-Cst·ARM Relaxed Model
- 39Cache Coherency 프로토콜 — MESI·MOESI·Snoop·Directory
- 40SMP 성능 분석 — Per-Core·Affinity·Load Balance·Scalability
- 41Linux perf 기초 — stat·record·report 활용
- 42Linux perf 고급 — Raw Event·Tracepoint·perf script
- 43ftrace 활용 — function·function_graph·latency tracer
- 44eBPF·bpftrace 동적 트레이싱 — 커널 무수정 관측
- 45Flamegraph 분석 — On-CPU·Off-CPU·Differential
- 46ARM DS·Lauterbach 분석 — Hardware Trace 전문 도구
- 47Bare-metal 프로파일링 — GPIO·DWT·SysTick·ITM 활용
- 48NVIDIA Nsight Systems — GPU·NPU 포함 시스템 분석
- 49모던 프로파일러 비교 — Tracy·Hotspot·uftrace·Coz
- 50연속 프로파일링 — Parca·Pixie·Pyroscope·Tetragon
- 51실전 사례 — ISR Latency 100µs Deadline Miss 추적
- 52실전 사례 — Matrix Multiply가 예상의 10배 느린 이유
- 53실전 사례 — 8-core가 4-core를 넘으면 throughput이 떨어지는 이유
- 54실전 사례 — 카메라 1080p 60fps가 30fps로 떨어지는 이유
- 55CXL.mem 지연·대역폭 실측 — Direct·Switch·Pooled 토폴로지 비교
- 56CXL 성능 프로파일링 도구 — cxl-cli·DAMON·perf-mem 활용
- 57실전 사례 — CXL.mem 추가로 LLM inference KV cache 처리량 회복
관련 글
Pipeline Stall 분석 — Data·Structural·Control Hazard·Forwarding
Stall은 pipeline bubble을 만듭니다. RAW·WAR·WAW hazard, forwarding, PMU STALL counter를 살펴봅니다.
DMA vs CPU Copy 성능 비교 — Break-even·Setup Overhead 실측
DMA setup overhead. CPU memcpy 최적화. Break-even size. 실측 데이터.
Speculative Execution 분석 — OoO·Reorder Buffer·Register Renaming
Out-of-order execution. ROB·issue queue·rename. Spectre 측면. Cortex-A 사례.