파이프라이닝 (Pipelining)

핵심 인사이트 (3줄 요약)

명령어 실행을 여러 단계로 분리하여 병렬 처리하는 기법으로, 한 클럭에 한 명령어가 완료되는 효과(이상적 CPI=1)를 얻는다. 데이터 해저드, 제어 해저드, 구조 해저드의 문제를 포워딩, 분기 예측, 자원 복제로 해결해야 한다. 현대 CPU는 15~20단계의 슈퍼파이프라인과 슈퍼스칼라 구조로 IPC 4~8을 달성한다.


Ⅰ. 개요 (필수: 200자 이상)

개념: 파이프라이닝(Pipelining)은 CPU 명령어 실행 과정을 여러 개의 독립적인 단계(Stage)로 분리하고, 각 단계가 서로 다른 명령어를 동시에 처리하도록 하여 처리량(Throughput)을 극대화하는 기법이다.

💡 비유: 파이프라이닝은 **"세탁소 컨베이어 벨트"**와 같다. 한 사람이 빨래를 다 접고 나서야 다음 사람이 빨래를 시작하면 느리다. 대신 분류→세탁→건조→다림질→포장 각 단계에 직원을 배치하면, 한 번에 여러 빨래가 동시에 처리된다. 5단계 파이프라인에서는 이론적으로 5배 더 많은 빨래를 처리할 수 있다.

등장 배경 (필수: 3가지 이상 기술):

  1. 기존 문제점 - 단일 사이클 비효율: 단일 사이클 CPU는 모든 명령어가 가장 긴 명령어(메모리 접근)의 실행 시간에 맞춰 클럭이 설정되어, 짧은 명령어(ADD)도 긴 시간을 낭비했다. 다중 사이클 CPU는 명령어별로 다른 클럭 수를 사용했지만 여전히 순차 실행만 가능했다.
  2. 기술적 필요성: 명령어 실행 단계(IF, ID, EX, MEM, WB)가 서로 독립적인 하드웨어(PC, 레지스터, ALU, 메모리)를 사용한다는 점을 활용하면, 동시에 여러 명령어의 서로 다른 단계를 병렬 처리할 수 있다.
  3. 시장/산업 요구: 소프트웨어의 복잡도 증가와 실시간 처리 요구사항으로 인해, 클럭 속도 향상만으로는 한계가 있어 아키텍처 수준의 병렬성이 필요하게 되었다.

핵심 목적: 클럭당 완료되는 명령어 수인 IPC(Instructions Per Cycle)를 높여, 동일 클럭 속도에서 처리량을 획기적으로 향상시키는 것이다.


Ⅱ. 구성 요소 및 핵심 원리 (필수: 가장 상세하게)

구성 요소 (필수: 최소 4개 이상):

구성 요소역할/기능특징비유
IF (Instruction Fetch)PC가 가리키는 명령어를 메모리에서 인출PC 갱신, 명령어 캐시 활용주문 받기
ID (Instruction Decode)명령어 해석, 레지스터 값 읽기제어 신호 생성, 데이터 준비레시피 확인
EX (Execute)ALU로 산술/논리 연산 수행주소 계산, 분기 목적지 계산요리 조리
MEM (Memory Access)메모리에서 데이터 로드/스토어데이터 캐시 활용재료 추가
WB (Write Back)결과를 목적지 레지스터에 저장레지스터 파일 쓰기플레이팅
파이프라인 레지스터단계 간 데이터 전달용 임시 저장IF/ID, ID/EX, EX/MEM, MEM/WB컨베이어 벨트
해저드 검출 유닛데이터/제어 의존성 탐지스톨 및 포워딩 제어품질 관리자
분기 예측기분기 방향 예측BHT, BTB, 2-bit 예측경험 많은 요리사

구조 다이어그램 (필수: ASCII 아트):

┌─────────────────────────────────────────────────────────────────────────────┐
│                      5단계 MIPS 파이프라인 구조                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  클럭:    1      2      3      4      5      6      7      8               │
│        ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐                  │
│  I1:   │ IF  │ ID  │ EX  │ MEM │ WB  │     │     │     │                  │
│        └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘                  │
│              ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐            │
│  I2:         │ IF  │ ID  │ EX  │ MEM │ WB  │     │     │     │            │
│              └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘            │
│                    ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐      │
│  I3:               │ IF  │ ID  │ EX  │ MEM │ WB  │     │     │     │      │
│                    └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘      │
│                          ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐      │
│  I4:                     │ IF  │ ID  │ EX  │ MEM │ WB  │     │     │      │
│                          └─────┴─────┴─────┴─────┴─────┴─────┴─────┘      │
│                                ┌─────┬─────┬─────┬─────┬─────┬─────┐      │
│  I5:                           │ IF  │ ID  │ EX  │ MEM │ WB  │     │      │
│                                └─────┴─────┴─────┴─────┴─────┴─────┘      │
│                                                                             │
│        ←─────── 5사이클 후 매 사이클마다 1개 명령어 완료 ───────→          │
│                                                                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                          파이프라인 하드웨어 구조                            │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐  │
│  │   IF    │───→│   ID    │───→│   EX    │───→│  MEM    │───→│   WB    │  │
│  │ 명령어  │    │ 명령어  │    │  실행   │    │ 메모리  │    │ 레지스터│  │
│  │  인출   │    │  해석   │    │         │    │  접근   │    │  쓰기   │  │
│  └─────────┘    └─────────┘    └─────────┘    └─────────┘    └─────────┘  │
│       ↑              ↑              ↑              ↑              ↑        │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐  │
│  │IF/ID    │    │ID/EX    │    │EX/MEM   │    │MEM/WB   │    │         │  │
│  │레지스터 │    │레지스터 │    │레지스터 │    │레지스터 │    │         │  │
│  └─────────┘    └─────────┘    └─────────┘    └─────────┘    └─────────┘  │
│       │              │              │              │                       │
│       ↓              ↓              ↓              ↓                       │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐                 │
│  │   PC    │    │레지스터 │    │   ALU   │    │ 데이터  │                 │
│  │ 명령어  │    │  파일   │    │         │    │ 메모리  │                 │
│  │ 캐시    │    │ 제어유닛│    │         │    │  캐시   │                 │
│  └─────────┘    └─────────┘    └─────────┘    └─────────┘                 │
└─────────────────────────────────────────────────────────────────────────────┘

동작 원리 (필수: 단계별 상세 설명):

① IF(인출) → ② ID(해석) → ③ EX(실행) → ④ MEM(메모리) → ⑤ WB(쓰기)
  • 1단계 - IF (Instruction Fetch, 명령어 인출):

    • PC(Program Counter) 값을 주소로 명령어 메모리 접근
    • 명령어 캐시에서 명령어 인출 (32bit/64bit)
    • PC 갱신: PC = PC + 4 (또는 분기 목적지)
    • IF/ID 파이프라인 레지스터에 명령어와 PC+4 저장
  • 2단계 - ID (Instruction Decode, 명령어 해석):

    • 명령어의 Opcode 필드 해석 → 제어 신호 생성
    • 레지스터 파일에서 Source 레지스터 값 읽기
    • Sign-Extend로 즉치값(Immediate) 확장
    • ID/EX 파이프라인 레지스터에 데이터 전달
  • 3단계 - EX (Execute, 실행):

    • ALU로 산술/논리 연산 수행
    • 메모리 주소 계산 (Base + Offset)
    • 분기 조건 평가 및 목적지 계산
    • EX/MEM 파이프라인 레지스터에 결과 저장
  • 4단계 - MEM (Memory Access, 메모리 접근):

    • Load: 데이터 캐시에서 메모리 값 읽기
    • Store: 데이터 캐시에 값 쓰기
    • 산술/논리 명령어는 이 단계를 통과만 함
    • MEM/WB 파이프라인 레지스터에 결과 전달
  • 5단계 - WB (Write Back, 레지스터 쓰기):

    • ALU 결과 또는 메모리에서 읽은 데이터를 목적지 레지스터에 저장
    • 레지스터 파일의 Write 포트 활용
    • 명령어 완료, 다음 명령어가 WB 단계에 진입

핵심 알고리즘/공식 (해당 시 필수):

파이프라인 성능 공식:
┌─────────────────────────────────────────────────────────────────┐
│  Speedup = n × t_nonpipelined / [(n + k - 1) × t_pipelined]    │
│                                                                 │
│  n: 명령어 수                                                   │
│  k: 파이프라인 단계 수                                          │
│  t: 클럭 주기                                                   │
│                                                                 │
│  이상적 (n → ∞): Speedup = k                                    │
│  5단계 파이프라인 → 최대 5배 향상                               │
├─────────────────────────────────────────────────────────────────┤
│  CPI (Cycles Per Instruction):                                  │
│  CPI_ideal = 1 (모든 단계 1 클럭씩)                             │
│  CPI_actual = 1 + Stall_Cycles_Per_Instruction                  │
│                                                                 │
│  예: 20% 분기, 2사이클 스톨 → CPI = 1 + 0.2×2 = 1.4            │
└─────────────────────────────────────────────────────────────────┘

파이프라인 효율:
Efficiency = (실제 처리 명령어 수) / (최대 처리 가능 명령어 수)
            = n / (n + k - 1)

예: 100개 명령어, 5단계
Efficiency = 100 / 104 = 96.2%

코드 예시 (필수: Python 또는 의사코드):

# 파이프라인 시뮬레이터
class PipelineSimulator:
    def __init__(self):
        # 파이프라인 레지스터
        self.if_id = {'ir': None, 'pc': 0}      # IF/ID
        self.id_ex = {'a': 0, 'b': 0, 'imm': 0,  # ID/EX
                      'op': None, 'rd': 0}
        self.ex_mem = {'result': 0, 'md': 0,     # EX/MEM
                       'op': None, 'rd': 0}
        self.mem_wb = {'result': 0, 'md': 0,     # MEM/WB
                       'op': None, 'rd': 0}

        # 하드웨어 자원
        self.pc = 0
        self.registers = [0] * 32
        self.memory = [0] * 1024
        self.instructions = []

        # 통계
        self.cycles = 0
        self.stalls = 0
        self.branch_mispredictions = 0

    def load_program(self, instructions):
        """프로그램 로드"""
        self.instructions = instructions
        self.pc = 0

    def step(self):
        """1 클럭 사이클 실행"""
        self.cycles += 1

        # 5단계 동시 실행 (역순으로 처리)
        self._writeback()
        self._memory()
        self._execute()
        self._decode()
        self._fetch()

    def _fetch(self):
        """IF 단계"""
        if self.pc < len(self.instructions):
            self.if_id['ir'] = self.instructions[self.pc]
            self.if_id['pc'] = self.pc
            self.pc += 1

    def _decode(self):
        """ID 단계"""
        if self.if_id['ir'] is not None:
            instr = self.if_id['ir']
            op, rd, rs, rt, imm = self._parse_instruction(instr)

            self.id_ex['op'] = op
            self.id_ex['rd'] = rd
            self.id_ex['a'] = self.registers[rs]
            self.id_ex['b'] = self.registers[rt]
            self.id_ex['imm'] = imm

    def _execute(self):
        """EX 단계"""
        if self.id_ex['op'] is not None:
            op = self.id_ex['op']

            if op == 'ADD':
                self.ex_mem['result'] = self.id_ex['a'] + self.id_ex['b']
            elif op == 'SUB':
                self.ex_mem['result'] = self.id_ex['a'] - self.id_ex['b']
            elif op == 'ADDI':
                self.ex_mem['result'] = self.id_ex['a'] + self.id_ex['imm']
            elif op == 'LW':
                self.ex_mem['result'] = self.id_ex['a'] + self.id_ex['imm']
            elif op == 'SW':
                self.ex_mem['result'] = self.id_ex['a'] + self.id_ex['imm']
                self.ex_mem['md'] = self.id_ex['b']
            elif op == 'BEQ':
                if self.id_ex['a'] == self.id_ex['b']:
                    self.pc = self.id_ex['imm']  # 분기

            self.ex_mem['op'] = op
            self.ex_mem['rd'] = self.id_ex['rd']

    def _memory(self):
        """MEM 단계"""
        if self.ex_mem['op'] is not None:
            op = self.ex_mem['op']

            if op == 'LW':
                self.mem_wb['md'] = self.memory[self.ex_mem['result']]
            elif op == 'SW':
                self.memory[self.ex_mem['result']] = self.ex_mem['md']

            self.mem_wb['op'] = op
            self.mem_wb['rd'] = self.ex_mem['rd']
            self.mem_wb['result'] = self.ex_mem['result']

    def _writeback(self):
        """WB 단계"""
        if self.mem_wb['op'] is not None:
            op = self.mem_wb['op']

            if op in ['ADD', 'SUB', 'ADDI', 'LW']:
                if op == 'LW':
                    self.registers[self.mem_wb['rd']] = self.mem_wb['md']
                else:
                    self.registers[self.mem_wb['rd']] = self.mem_wb['result']

    def _parse_instruction(self, instr):
        """명령어 파싱"""
        parts = instr.replace(',', ' ').split()
        op = parts[0]

        if op in ['ADD', 'SUB']:
            rd = int(parts[1][1:])
            rs = int(parts[2][1:])
            rt = int(parts[3][1:])
            return op, rd, rs, rt, 0
        elif op == 'ADDI':
            rd = int(parts[1][1:])
            rs = int(parts[2][1:])
            imm = int(parts[3])
            return op, rd, rs, 0, imm
        elif op == 'LW':
            rd = int(parts[1][1:])
            return op, rd, 0, 0, 0
        return op, 0, 0, 0, 0

    def run(self, max_cycles=100):
        """프로그램 실행"""
        for _ in range(max_cycles):
            self.step()
            if self.pc >= len(self.instructions) and self._pipeline_empty():
                break
        return self.cycles

    def _pipeline_empty(self):
        return (self.if_id['ir'] is None and
                self.id_ex['op'] is None and
                self.ex_mem['op'] is None and
                self.mem_wb['op'] is None)


# 사용 예시
sim = PipelineSimulator()
program = [
    'ADD R1, R2, R3',   # R1 = R2 + R3
    'ADD R4, R1, R5',   # R4 = R1 + R5 (데이터 해저드!)
    'ADDI R6, R6, 1',   # R6 = R6 + 1
    'ADD R7, R8, R9',   # R7 = R8 + R9
]

sim.load_program(program)
sim.registers[2] = 10
sim.registers[3] = 20
sim.registers[5] = 5

cycles = sim.run()
print(f"실행 완료: {cycles} 클럭 사이클")
print(f"R1 = {sim.registers[1]}")  # 30
print(f"R4 = {sim.registers[4]}")  # 35

Ⅲ. 기술 비교 분석 (필수: 2개 이상의 표)

장단점 분석 (필수: 최소 3개씩):

장점단점
처리량 향상: 이상적 IPC = 1 (클럭당 1명령어)해저드 처리 복잡: 데이터/제어/구조 의존성
하드웨어 효율: 각 단계 전담 하드웨어 활용분기 비용: 예측 실패 시 파이프라인 플러시
높은 클럭 가능: 각 단계가 단순해짐설계 복잡도: 포워딩, 예측 로직 필요
투명성: 프로그래머가 인지할 필요 없음파이프라인 플러시 비용: 10~20 사이클 손실

파이프라인 해저드 유형 및 해결책 비교 (필수: 최소 2개 대안):

해저드 유형원인문제 상황해결 방법패널티
데이터 해저드 (Data)이전 명령어 결과를 다음 명령어가 사용ADD R1,R2,R3 → SUB R4,R1,R5포워딩(Forwarding), 스톨, 재배치0~3 cycle
제어 해저드 (Control)분기 명령어로 PC 변경BEQ 후 다음 명령어 실행 여부분기 예측, 지연 슬롯, 스톨1~20 cycle
구조 해저드 (Structural)동시에 같은 자원 사용두 명령어가 동시 메모리 접근자원 복제, 하버드 구조1~2 cycle

★ 선택 기준:

  • 데이터 해저드: 포워딩을 기본으로, 해결 안 되면 스톨
  • 제어 해저드: 동적 분기 예측(90%+ 정확도)으로 미스 최소화
  • 구조 해저드: 하버드 구조(명령어/데이터 메모리 분리)로 사전 차단

분기 예측 기법 비교:

기법원리정확도하드웨어 비용사용처
정적 예측 (Always Not Taken)분기 안 함으로 가정50%없음초기 CPU
정적 예측 (Backward Taken)뒤로 분기면 루프→분기65%없음간단한 시스템
1-bit 예측직전 결과 사용80%매우 낮음임베디드
2-bit 예측상태 머신(Strong/Weak)90%낮음★ 실제 CPU
BHT (Branch History Table)PC 기반 이력 저장93%중간★ 현대 CPU
2-level 예측전역+지역 이력 조합97%높음고성능 CPU
신경망 예측Perceptron 기반99%+매우 높음최신 CPU

Ⅳ. 실무 적용 방안 (필수: 기술사 판단력 증명)

기술사적 판단 (필수: 3개 이상 시나리오):

적용 분야구체적 적용 방법기대 효과 (정량)
CPU 아키텍처 설계슈퍼스칼라(4-way issue) + 비순차 실행 + 15단계 파이프라인IPC 4~6 달성
임베디드 시스템ARM Cortex-M 3단계 파이프라인, 저전력 최적화전력 대비 성능 최적화
컴파일러 최적화루프 언롤링, 명령어 스케줄링으로 해저드 회피CPI 20~40% 개선
실시간 시스템WCET(Worst Case Execution Time) 분석 시 파이프라인 영향 고려보수적 예측으로 데드라인 보장

실제 도입 사례 (필수: 구체적 기업/서비스):

  • 사례 1: 인텔 Core 아키텍처 - 14~19단계 파이프라인, 4-way 슈퍼스칼라, 분기 예측 정확도 97%+ 달성. 비순차 실행으로 IPC 4 이상.
  • 사례 2: ARM Cortex-A78 - 11단계 파이프라인, 4-way issue, 모바일용 저전력 설계. 3GHz 동작으로 AI 추론 가속.
  • 사례 3: Apple M2 - 10단계 파이프라인, 8-wide decode, 128개 재정렬 버퍼. IPC 6~8 달성으로 x86 대비 동전력 2배 성능.

도입 시 고려사항 (필수: 4가지 관점):

  1. 기술적:

    • 파이프라인 단계 수 결정 (깊을수록 높은 클럭, 해저드 패널티 증가)
    • 슈퍼스칼라 설계 (Issue Width, Reservation Station)
    • 비순차 실행 범위 (Reorder Buffer 크기)
    • 분기 예측 정확도 목표
  2. 운영적:

    • 컴파일러 지원 (명령어 스케줄링, 루프 최적화)
    • 디버깅 복잡도 (파이프라인 상태 추적 어려움)
    • 성능 프로파일링 (해저드 빈도 분석)
    • 검증 및 테스트 (모든 파이프라인 조합 테스트)
  3. 보안적:

    • Spectre 공격: 투기적 실행 악용
    • 파이프라인 사이드 채널: 타이밍 정보 유출
    • 추측 실행 버퍼 오버플로우
    • 완화: Retpoline, KPTI
  4. 경제적:

    • 설계 복잡도 증가 → 개발 비용 상승
    • 검증 비용 (파이프라인 버그는 치명적)
    • 클럭 속도 vs 전력 소비 트레이드오프
    • 성능 대비 수확 체감 (단계 수 무한 증가 불가)

주의사항 / 흔한 실수 (필수: 최소 3개):

  • 파이프라인 너무 깊게 설계: Intel NetBurst (31단계)는 높은 클럭이지만 분기 미스 페널티 과대 → 실패
  • 분기 예측 무시: 분기 미스 1회당 10~20 사이클 손실, 전체 성능 20~30% 저하 가능
  • 데이터 의존성 간과: 컴파일러가 스케줄링 안 하면 포워딩으로도 해결 안 되는 경우 존재

관련 개념 / 확장 학습 (필수: 최소 5개 이상 나열):

📌 파이프라이닝 핵심 연관 개념 맵

┌─────────────────────────────────────────────────────────────────┐
│                      파이프라이닝                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  해저드 ←──→ 파이프라인 ←──→ 슈퍼스칼라                         │
│     ↓            ↓              ↓                               │
│  포워딩      명령어사이클    비순차실행                          │
│     ↓            ↓              ↓                               │
│  분기예측      CPU구조      재정렬버퍼                           │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
관련 개념관계설명문서 링크
해저드 (Hazard)핵심 문제데이터/제어/구조 의존성으로 파이프라인 중단[해저드](./hazard.md)
명령어 사이클기반 개념IF-ID-EX-MEM-WB 5단계 구성[명령어 사이클](./instruction_cycle.md)
CPU 구조하드웨어 기반파이프라인 레지스터, ALU, 메모리[CPU](./cpu.md)
슈퍼스칼라확장 기술여러 명령어 동시 발송 (Multi-issue)[슈퍼스칼라](./superscalar.md)
분기 예측제어 해저드 해결BHT, BTB로 분기 방향 예측[분기 예측](./branch_prediction.md)
비순차 실행성능 향상의존성 없는 명령어 먼저 실행[비순차 실행](./out_of_order.md)
캐시 메모리메모리 계층캐시 미스 시 파이프라인 스톨[캐시 메모리](./cache_memory.md)

Ⅴ. 기대 효과 및 결론 (필수: 미래 전망 포함)

정량적 기대 효과 (필수):

효과 영역구체적 내용정량적 목표
처리량클럭당 완료 명령어 수 증가단일 사이클 대비 4~8배 향상
클럭 속도각 단계 단순화로 높은 클럭3~5GHz 이상 동작
전력 효율스톨 감소로 유휴 전력 절감동성능 대비 전력 30% 절감
응답성높은 IPC로 실행 시간 단축응답 지연 50% 이상 감소

미래 전망 (필수: 3가지 관점):

  1. 기술 발전 방향:

    • VLIW/EPIC: 컴파일러가 명령어 병렬성 결정 (Itanium 시도, 한계)
    • Systolic Array: AI 가속기용 파이프라인 (TPU, 데이터 흐름)
    • 에너지 효율 파이프라인: Clock Gating, Power Gating 강화
  2. 시장 트렌드:

    • AI 추론용 단순 파이프라인 (RISC-V, ARM)
    • 이종 코어 파이프라인 (big.LITTLE, DynamIQ)
    • 실시간 시스템용 예측 가능 파이프라인
  3. 후속 기술:

    • 양자 파이프라인: 양자 게이트 병렬 실행
    • 광(Photonics) 파이프라인: 광 인터커넥트로 지연 최소화
    • 뉴로모픽 파이프라인: 스파이킹 신경망 기반 처리

결론: 파이프라이닝은 현대 CPU 성능의 핵심 기반 기술로, 해저드 관리의 정교함이 실제 성능을 결정한다. 슈퍼스칼라, 비순차 실행, 분기 예측과 결합하여 IPC 4~8을 달성하며, AI 가속기의 Systolic Array로도 진화하고 있다.

※ 참고 표준: Patterson & Hennessy "Computer Organization and Design", MIPS32 Architecture, ARM Architecture Reference Manual, Intel 64 SDM


어린이를 위한 종합 설명 (필수)

파이프라이닝은 "피자 가게 컨베이어 벨트"야!

피자 가게에서 피자를 만들 때, 한 명이 처음부터 끝까지 다 하면 느려요. 도우를 펴고 → 소스를 바르고 → 토핑을 올리고 → 굽고 → 포장하는데 5분이 걸린다고 해봐요.

옛날 방식 (파이프라인 없음):

요리사 1: [피자1 도우][소스][토핑][굽기][포장] (5분)
요리사 1:                           [피자2 도우][소스]...

→ 5분에 피자 1개밖에 못 만들어요! 😢

파이프라인 방식:

도우 담당:  [피자1][피자2][피자3][피자4][피자5]
소스 담당:        [피자1][피자2][피자3][피자4]
토핑 담당:              [피자1][피자2][피자3]
굽기 담당:                   [피자1][피자2]
포장 담당:                        [피자1]

→ 5번째 분부터는 1분마다 피자 1개씩 완성! 🍕

문제점들 (해저드):

  1. 데이터 해저드: "치즈 다 썼어요!" → 옆 친구에게 바로 전달받기 (포워딩)
  2. 제어 해저드: "오늘은 쉬는 날인가?" → 미리 예측해서 준비 (분기 예측)
  3. 구조 해저드: "오븐이 하나예요!" → 오븐 두 개 설치 (자원 복제)

비밀: 요즘 컴퓨터(CPU)는 20단계 컨베이어 벨트를 사용해서 엄청나게 빨라요! 🏃💨