Computer Architecture - Ch3
명령어 수준 병렬성
Instruction-Level Parallelism
단일 프로세서의 극한 성능을 추구하는 ILP — Tomasulo 알고리즘, 투기적 실행, 분기 예측부터 2026년 최신 마이크로아키텍처까지
🚀 1. ILP란 무엇인가? — 단일 코어의 숨겨진 병렬성
명령어 수준 병렬성(Instruction-Level Parallelism, ILP)은 프로그램 내의 서로 독립적인 명령어들을 동시에 실행하여 성능을 높이는 기법입니다. 프로그래머가 순차적으로 작성한 코드 속에서도, 하드웨어나 컴파일러가 병렬 실행 가능한 명령어들을 찾아내어 CPI(Cycles Per Instruction)를 1 이하로 낮추는 것이 궁극적 목표입니다.
1990년대부터 2000년대 중반까지 프로세서 성능 향상의 핵심 동력이었던 ILP는, 전력 장벽(Power Wall)과 복잡도 한계로 인해 단독으로는 한계에 도달했지만, 오늘날에도 모든 고성능 CPU의 핵심 기반 기술로 작동하고 있습니다. 2026년 현재 AMD Zen 5의 ROB 448 엔트리, Intel Lion Cove의 576 엔트리 ROB, Apple M4의 ~630 엔트리 OoO 윈도우는 ILP가 여전히 진화하고 있음을 보여줍니다.
448
AMD Zen 5 ROB 엔트리
576
Intel Lion Cove ROB
~630
Apple M4 OoO Window
99%+
현대 분기 예측 정확도
🔗 2. 의존성 (Dependences) — ILP의 근본 장벽
명령어들을 병렬로 실행하기 위해서는 명령어 간의 의존성(Dependence)을 파악하고 해결해야 합니다. 의존성이 곧 해저드(Hazard)를 만들고, 해저드가 스톨(Stall)을 발생시켜 성능을 떨어뜨립니다.
📌 2.1 데이터 의존성 (True Data Dependence)
RAW(Read After Write) — 뒤의 명령어가 앞의 명령어의 결과값을 필요로 하는 진정한 의존성(True Dependence)입니다. 이것은 프로그램의 의미(Semantics)를 나타내므로 근본적으로 제거할 수 없습니다.
DIV.D F0, F2, F4 ; F0 = F2 / F4 (12 사이클) ADD.D F10, F0, F8 ; F0를 읽어야 함 → RAW! SUB.D F12, F8, F14 ; F0와 무관 → 독립적!
위 코드에서 ADD.D는 DIV.D의 결과(F0)를 기다려야 하지만, SUB.D는 F0와 무관하므로 독립적으로 실행할 수 있습니다. 포워딩(Forwarding/Bypassing) 기법으로 지연을 줄일 수 있지만, 연산 자체의 지연시간(Latency)은 줄일 수 없습니다.
📌 2.2 이름 의존성 (Name Dependence)
두 명령어가 같은 레지스터를 사용하지만, 실제 데이터 흐름(값의 전달)은 없는 "거짓" 의존성입니다. 레지스터 이름이 충돌할 뿐이므로 레지스터 재명명(Register Renaming)으로 완전히 제거할 수 있습니다.
| 종류 | 약자 | 상황 | 예시 | 해결 |
|---|---|---|---|---|
| 반의존성 | WAR | 뒤 명령어가 먼저 쓰면 앞 명령어가 잘못된 값을 읽음 | ADD F6,F0,F8 → SUB F8,F10,F14 | Register Renaming |
| 출력 의존성 | WAW | 두 명령어가 같은 대상에 쓰면 최종 결과가 꼬임 | ADD F6,F0,F8 → MUL F6,F10,F8 | Register Renaming |
; 원본 (WAR + WAW 위험) DIV.D F0, F2, F4 ADD.D F6, F0, F8 ; F6에 쓰기 S.D F6, 0(R1) ; F6 읽기 SUB.D F8, F10, F14 ; F8에 쓰기 → WAR (ADD가 F8 읽기 전) MUL.D F6, F10, F8 ; F6에 쓰기 → WAW (ADD도 F6 쓰기) ; 재명명 후 (임시 레지스터 S, T 사용) DIV.D F0, F2, F4 ADD.D S, F0, F8 ; F6 → S로 재명명 S.D S, 0(R1) ; S 읽기 SUB.D T, F10, F14 ; F8 → T로 재명명 MUL.D F6, F10, T ; 이제 모든 WAR/WAW 제거!
📌 2.3 제어 의존성 (Control Dependence)
분기문(Branch)의 결과에 따라 실행될 명령어가 결정됩니다. 프로그램 코드에서 평균적으로 약 6개 명령어마다 1개의 분기가 등장하므로, 분기 예측이 정확하지 않으면 파이프라인 효율이 크게 떨어집니다. 이를 해결하기 위해 분기 예측(Branch Prediction)과 투기적 실행(Speculation)이 사용됩니다.
💡 의존성 vs 해저드 vs 스톨
의존성(Dependence)은 프로그램 자체의 속성이며, 코드가 바뀌지 않는 한 존재합니다.
해저드(Hazard)는 특정 파이프라인 구조에서 의존성이 발생시키는 문제입니다.
스톨(Stall)은 해저드를 해결하기 위해 파이프라인이 실제로 멈추는 현상입니다.
⚙️ 3. 동적 스케줄링: Tomasulo 알고리즘
동적 스케줄링(Dynamic Scheduling)은 하드웨어가 런타임에 명령어의 실행 순서를 재배치하여 스톨을 최소화하는 기법입니다. 프로그램에 작성된 순서(In-order)와 상관없이, 실행 준비가 완료된 명령어부터 먼저 실행(Out-of-Order Execution)하여 파이프라인의 빈 슬롯을 채웁니다.
🏭 3.1 왜 동적 스케줄링인가?
정적(In-order) 파이프라인에서는 앞 명령어가 멈추면 뒤의 모든 명령어도 함께 멈춥니다. 예를 들어 DIV.D(12사이클)가 실행 중이면, 그와 무관한 SUB.D도 대기해야 합니다. 동적 스케줄링은 이런 불필요한 대기를 제거합니다.
동적 스케줄링의 세 가지 핵심 이점은 다음과 같습니다. 첫째, 하나의 바이너리가 다른 파이프라인 구조에서도 효율적으로 동작합니다(바이너리 호환성). 둘째, 포인터나 동적 링킹 등 컴파일 시점에 알 수 없는 의존성을 런타임에 해결합니다. 셋째, 캐시 미스와 같은 예측 불가능한 지연 시간을 숨길 수 있습니다.
🏭 3.2 Tomasulo 알고리즘의 핵심 구조
IBM 360/91(1967년)에서 Robert Tomasulo가 발명한 이 알고리즘은 세 가지 하드웨어 구조를 활용합니다:
① 예약역 (Reservation Station)
각 연산기(ALU/FPU) 앞에 위치한 버퍼로, 명령어가 실행을 기다리는 장소입니다. 피연산자가 이미 준비되었다면 값(Vj, Vk)을 저장하고, 아직 준비되지 않았다면 그 값을 생성할 예약역의 태그(Qj, Qk)를 기록합니다. 예약역의 수가 실제 레지스터보다 많으므로, 이 태그를 통한 재명명은 컴파일러보다 더 많은 이름 의존성을 제거할 수 있습니다.
| 필드 | 설명 |
|---|---|
| Op | 수행할 연산 (ADD, MUL, DIV 등) |
| Vj, Vk | 소스 피연산자의 실제 값 (준비된 경우) |
| Qj, Qk | 값을 생성할 예약역의 번호/태그 (아직 미준비인 경우). 0이면 값이 준비됨 |
| A | Load/Store의 메모리 주소 (유효 주소 계산 후 저장) |
| Busy | 이 예약역이 사용 중인지 표시 |
② 레지스터 재명명 (Register Renaming)
명령어가 예약역으로 발행될 때, 목적지 레지스터는 예약역 번호로 대체됩니다. 이후 이 레지스터를 참조하는 명령어는 레지스터 파일이 아닌 해당 예약역을 가리킵니다. 이렇게 레지스터 이름 대신 예약역 태그를 사용하므로 WAR, WAW 해저드가 하드웨어적으로 완전히 제거됩니다.
③ 공통 데이터 버스 (Common Data Bus, CDB)
연산이 완료된 결과를 레지스터 파일을 거치지 않고 CDB를 통해 모든 대기 중인 예약역에 동시 브로드캐스트합니다. 여러 예약역이 같은 값을 기다리고 있었다면, 하나의 브로드캐스트로 모두 동시에 해제됩니다. 이것은 정적 파이프라인의 포워딩을 일반화한 것이며, RAW 해저드에 의한 지연을 최소화합니다.
TOMASULO 프로세서 구조
Load Buffer
주소 → 메모리 읽기
RS: FP Adders
Add1, Add2, Add3
RS: FP Multipliers
Mult1, Mult2
Store Buffer
값 대기 → 메모리 쓰기
🔄 3.3 실행 3단계
Issue
Execute
Write Result
① 발행(Issue): 명령어 큐의 선두에서 명령어를 가져와 빈 예약역에 할당합니다. 피연산자가 레지스터에 준비되어 있으면 값(V)을 복사하고, 아직 계산 중이면 생성할 예약역의 태그(Q)를 기록합니다. 이 단계에서 레지스터 재명명이 수행되어 WAR/WAW 해저드가 제거됩니다. 빈 예약역이 없으면 구조적 해저드로 스톨됩니다.
② 실행(Execute): 모든 피연산자가 준비되면(Qj=0, Qk=0) 연산기에서 비순차적으로 실행합니다. CDB를 모니터링하면서 필요한 피연산자가 브로드캐스트되면 즉시 캡처합니다. 여러 명령어가 동시에 준비될 수 있으며, 각 연산기에서 독립적으로 실행됩니다. Load/Store는 먼저 유효 주소를 계산한 후 메모리 접근을 수행합니다.
③ 기록(Write Result): 연산 완료 후 결과를 CDB에 실어 브로드캐스트합니다. 이 결과를 기다리는 모든 예약역과 레지스터 파일이 동시에 업데이트됩니다. Store의 경우, 저장할 값과 주소가 모두 준비되면 메모리에 기록합니다.
🔁 3.4 루프에서의 동적 언롤링
Tomasulo 알고리즘의 강력한 장점 중 하나는 루프의 여러 반복을 하드웨어적으로 동시 실행할 수 있다는 것입니다. 각 반복에서 같은 레지스터를 사용하더라도, 예약역이 자동으로 재명명 역할을 하므로 코드를 변경하지 않고도 루프가 동적으로 언롤됩니다.
Loop: L.D F0, 0(R1) ; 배열 요소 로드 MUL.D F4, F0, F2 ; 스칼라 곱셈 S.D F4, 0(R1) ; 결과 저장 DADDIU R1, R1, -8 ; 포인터 감소 BNE R1, R2, Loop ; 반복
분기를 taken으로 예측하면, 두 번째 반복의 L.D는 Load2 예약역에, 두 번째 MUL.D는 Mult2에 할당됩니다. 각 반복이 서로 다른 예약역에 있으므로, 첫 번째 반복의 결과를 기다리는 동안 두 번째 반복이 독립적으로 진행됩니다.
🎯 4. 하드웨어 기반 분기 예측 (Branch Prediction)
파이프라인이 깊어지고 다중 발행(Multiple Issue)이 도입될수록, 분기 예측 실패의 페널티가 기하급수적으로 커집니다. 현대 프로세서에서는 매 사이클마다 분기를 정확히 예측해야 파이프라인이 효율적으로 동작합니다.
📊 4.1 상관 분기 예측기 (Correlating Predictor)
특정 분기의 결과가 이전 분기들의 결과와 상관관계를 가진다는 관찰에 기반합니다. (m, n) 예측기는 최근 m개 분기의 결과(Global History)를 이용하여 2m개의 상황별로 n-비트 카운터를 유지합니다.
📐 (2, 2) 상관 예측기 예시
최근 2개 분기 결과: TN (Taken-Not Taken)
이 히스토리를 인덱스로 사용하여 해당 2-비트 포화 카운터 참조
2-비트 카운터: 00(강한 NT) → 01(약한 NT) → 10(약한 T) → 11(강한 T)
결과: 한 번의 예측 실패만으로 전체 예측 방향이 바뀌지 않음 (히스테리시스 효과)
🏆 4.2 토너먼트 예측기 (Tournament Predictor)
두 개 이상의 서로 다른 예측기를 결합하고, 선택기(Selector)가 어떤 예측기가 현재 분기에 더 정확한지 추적합니다. 일반적으로 지역 이력 예측기(Local History)와 전역 이력 예측기(Global History)를 결합합니다.
지역 이력 예측기는 개별 분기 PC의 과거 패턴(예: TTNTTNTTN...)을 추적하여, 특정 분기의 고유한 행동 패턴을 학습합니다. 전역 이력 예측기는 최근 실행된 모든 분기의 결과 패턴을 사용하여, 분기 간 상관관계를 포착합니다. 선택기는 두 예측기 중 최근 더 정확했던 것을 선택하므로, 단일 예측기보다 일관되게 높은 정확도를 달성합니다.
📦 4.3 BTB (Branch Target Buffer)
BTB는 분기문의 대상 주소(Target Address)를 캐싱하는 하드웨어 구조입니다. Fetch 단계에서 현재 PC로 BTB를 검색하여, 히트하면 그 명령어가 분기임과 동시에 타겟 주소를 즉시 알 수 있습니다. 이를 통해 분기 판별과 타겟 계산에 의한 지연 없이, 다음 사이클부터 바로 타겟 주소의 명령어를 페치할 수 있습니다.
Return 명령어에 대해서는 Return Address Stack(RAS)이 별도로 사용됩니다. 함수 호출 시 반환 주소를 스택에 push하고, return 시 pop하여 정확한 반환 주소를 예측합니다.
🎲 5. 투기적 실행 (Hardware-Based Speculation)
동적 스케줄링만으로는 분기 결과가 확정될 때까지 후속 명령어의 실행이 제한됩니다. 투기적 실행(Speculation)은 분기 예측을 바탕으로 예측된 경로의 명령어를 미리 fetch, issue, execute하는 기법입니다. 예측이 맞으면 성능 향상을 얻고, 틀리면 결과를 폐기(Rollback)합니다.
📋 5.1 재주문 버퍼 (Reorder Buffer, ROB)
투기적 실행의 핵심은 실행은 비순차(Out-of-Order)로, 커밋은 순차(In-Order)로라는 원칙입니다. 이를 위해 Tomasulo 알고리즘에 ROB(Reorder Buffer)가 추가됩니다.
| ROB 필드 | 설명 |
|---|---|
| Instruction Type | 분기 / Store / 레지스터 연산(ALU/Load) 구분 |
| Destination | 결과가 기록될 레지스터 번호 또는 메모리 주소 |
| Value | 명령어의 실행 결과 (커밋 전 임시 저장) |
| Ready | 실행 완료 여부 표시 |
🔄 5.2 투기적 실행의 4단계
Issue
Execute
Write Result
Commit
① 발행(Issue): Tomasulo와 동일하되, ROB 엔트리도 함께 할당합니다. 피연산자는 레지스터 파일 또는 ROB에서 가져옵니다.
② 실행(Execute): 피연산자가 모두 준비되면 비순차적으로 실행합니다. Tomasulo와 동일한 방식입니다.
③ 기록(Write Result): 결과를 CDB를 통해 브로드캐스트하되, 레지스터 파일이 아닌 ROB에 임시 저장합니다. 대기 중인 예약역도 이 값을 받습니다.
④ 커밋(Commit): ROB 선두의 명령어가 실행 완료되고, 분기 예측이 정확하며, 예외가 없을 때만 결과를 실제 레지스터/메모리에 영구 기록합니다. 분기 예측이 틀렸다면 ROB를 플러시하고 올바른 경로에서 재시작합니다.
✅ 정밀 예외(Precise Exception) 보장
순차 커밋 덕분에 예외 발생 시 프로세서 상태가 프로그램 순서와 정확히 일치합니다. Tomasulo 원본에서는 비순차 완료로 인해 불정밀 예외가 발생할 수 있었지만, ROB 추가로 이 문제가 완전히 해결됩니다.
🚄 6. 다중 명령 발행 (Multiple Issue)
CPI를 1 이하로 낮추려면(IPC > 1) 한 사이클에 여러 명령어를 동시에 발행해야 합니다. 이를 위한 두 가지 주요 접근법이 있습니다.
| 구분 | 슈퍼스칼라 (Superscalar) | VLIW |
|---|---|---|
| 스케줄링 | 동적 — 하드웨어가 런타임에 의존성 분석 | 정적 — 컴파일러가 사전에 스케줄링 |
| 발행 폭 | 동적 결정 (1~N개) | 고정 (하나의 긴 명령어 워드) |
| 하드웨어 복잡도 | 높음 (의존성 검사 하드웨어) | 낮음 (간단한 파이프라인) |
| 컴파일러 부담 | 낮음 | 높음 (NP-hard 스케줄링) |
| 바이너리 호환성 | 높음 (다른 구현에서도 동작) | 낮음 (파이프라인 변경 시 재컴파일) |
| 대표 프로세서 | Intel Core i7, AMD Zen, Apple M4, ARM Cortex-A9+ | Intel Itanium (IA-64), TI C6x DSP |
Intel Itanium(IA-64)은 VLIW 계열의 가장 야심찬 시도였지만, 범용 정수 코드에서 기대에 미치지 못했고, 결국 2021년에 단종되었습니다. 업계는 3~6-wide 동적 스케줄링 슈퍼스칼라가 복잡도와 성능의 최적 균형임을 발견했습니다.
🧵 7. 멀티스레딩 — ILP를 넘어서
ILP만으로는 긴 캐시 미스 지연을 숨기기 어렵습니다. 멀티스레딩(Multithreading)은 하나의 프로세서 코어에서 여러 스레드의 명령어를 교차 실행하여, 한 스레드가 스톨되는 동안 다른 스레드가 실행 자원을 활용하는 기법입니다.
| 방식 | 스레드 전환 시점 | 장점 | 단점 | 대표 예 |
|---|---|---|---|---|
| 세밀한 MT | 매 사이클 (라운드 로빈) | 짧은/긴 스톨 모두 숨김 | 개별 스레드 지연 증가 | Sun T1/T2, NVIDIA GPU |
| 거친 MT | L2/L3 미스 같은 긴 스톨 시 | 개별 스레드 성능 유지 | 짧은 스톨 숨기기 어려움 | (연구 프로세서) |
| SMT | 동일 사이클에 여러 스레드 | 실행 자원 최대 활용 | 복잡한 하드웨어, 보안 우려 | Intel HT, AMD SMT, IBM Power |
SMT(Simultaneous Multithreading)는 동적 스케줄링 위에 멀티스레딩을 구현한 것으로, 레지스터 재명명과 비순차 실행 하드웨어가 이미 존재하기 때문에 비교적 적은 추가 하드웨어(스레드별 레지스터 파일, PC, 페이지 테이블)로 구현됩니다. Intel i7의 SMT(2스레드)는 평균 28~31% 성능 향상을 제공하면서 에너지 효율도 개선합니다.
🚧 8. ILP의 한계 (Limits of ILP)
하드웨어와 소프트웨어의 극단적인 최적화에도 불구하고, ILP를 통한 성능 향상에는 물리적·논리적 한계가 존재합니다. 이론적으로 무한한 자원을 가정하면 IPC가 수십~수백에 달할 수 있지만, 현실적 제약 아래에서는 IPC 3~6 수준이 실질적 한계입니다.
| 한계 요인 | 설명 | 영향 |
|---|---|---|
| 명령어 윈도우 크기 | 동시에 의존성을 검사할 수 있는 명령어 수 (ROB 크기). 하드웨어 복잡도가 O(n²)으로 증가 | 윈도우를 2배 늘려도 IPC 10~15% 증가에 그침 |
| 분기 예측 한계 | 99% 정확도에도 매 100번째 분기에서 파이프라인 전체 플러시 발생 | Wide issue에서 1%의 실패 = 수십 명령어 낭비 |
| 레지스터 수 제한 | 물리 레지스터 수가 유한하여 동시에 비행 중인 명령어 수 제한 | 재명명 가능한 레지스터 부족 → 발행 스톨 |
| 메모리 주소 모호성 | 포인터를 통한 메모리 접근은 런타임에만 주소 확인 가능 | Load/Store 재배치 제한, 보수적 스케줄링 |
| 전력 장벽 (Power Wall) | 복잡한 OoO 하드웨어의 전력 소모가 성능 이득보다 빠르게 증가 | 단일 코어 복잡도 증가의 실질적 종착점 |
⚠️ ILP의 한계가 이끈 패러다임 전환
2000년대 초반, Intel의 Pentium 4 NetBurst(31단 파이프라인)와 같은 극단적 ILP 추구는 전력과 복잡도의 벽에 부딪혔습니다. 이후 업계는 단일 코어 복잡성을 높이는 대신 멀티코어(TLP, Chapter 5)와 데이터 수준 병렬성(DLP, Chapter 4)을 강조하는 방향으로 전환했습니다. 하지만 ILP는 여전히 각 코어의 근본 기반으로, 완전히 포기된 것이 아니라 "균형 있는 투자" 대상이 되었습니다.
🔬 9. 실전 사례: ARM Cortex-A8 vs Intel Core i7
교재에서는 두 가지 대조적인 프로세서를 비교합니다: 단순한 정적 스케줄링의 ARM Cortex-A8과 공격적인 동적 스케줄링의 Intel Core i7입니다.
| 특성 | ARM Cortex-A8 | Intel Core i7 (Nehalem) |
|---|---|---|
| 발행 폭 | 2-way 정적 슈퍼스칼라 | 4-way 동적 슈퍼스칼라 |
| 스케줄링 | 정적 (컴파일러 + 스코어보드) | 동적 (Tomasulo + 투기적 실행) |
| 파이프라인 깊이 | 13단 | 14~19단 |
| 분기 예측 | 512-entry BTB + 4K GHB | 토너먼트 예측기, 대형 BTB |
| 분기 미스 페널티 | 13 사이클 | 17~20+ 사이클 |
| 비순차 실행 | 없음 (In-order) | 있음 (128-entry ROB) |
| SMT | 없음 | 2스레드 (Hyper-Threading) |
| 설계 목표 | 저전력, 소형 (모바일) | 최고 성능 (데스크톱/서버) |
A8의 CPI 분석에서 파이프라인 스톨이 가장 큰 성능 저하 요인이었으며, 이 관찰이 후속 모델 Cortex-A9에서 동적 스케줄링을 도입하는 결정적 이유가 되었습니다. A9는 A8 대비 평균 1.28배의 성능 향상을 달성했습니다 (동일 클럭 기준).
🔮 10. 2026년 업데이트 — 현대 프로세서의 ILP
교재의 기본 원리는 변하지 않았지만, 2026년 현재 프로세서의 ILP 구현은 규모와 정교함에서 비약적으로 발전했습니다.
🔧 10.1 AMD Zen 5 (2024) — 16% IPC 향상의 해부
AMD의 Zen 5는 Zen 4 대비 16% IPC 향상을 달성했으며, 이는 "ground-up redesign"의 결과입니다.
448
ROB 엔트리 (Zen 4: 320)
8-wide
정수 재명명 폭
2-Ahead
분기 예측기 (2블록 선행)
512-bit
네이티브 AVX-512
2-Ahead Branch Predictor: Zen 5의 가장 혁신적인 변화 중 하나는 분기 예측기가 한 번에 두 개의 기본 블록(Basic Block)을 예측하는 것입니다. 일반적으로 약 6개 명령어마다 분기가 등장하므로, 기존 1-블록 예측기로는 fetch 대역폭을 완전히 활용하기 어려웠습니다. 2-Ahead 예측기는 관련 하드웨어(BTB, 분기 이력 테이블)를 듀얼 포트화하여 3개의 예측 윈도우를 동시에 처리합니다.
듀얼 디코드 클러스터: Zen 5는 두 개의 4-wide 디코드 클러스터를 가지며, SMT 모드에서 각 스레드에 하나씩 할당됩니다. 단일 스레드 모드에서는 하나의 클러스터만 사용하는데, 이는 두 클러스터의 비순차 명령어 스트림을 다시 순서대로 합치는 것이 어렵기 때문입니다.
ROB 192 → 320 → 448 진화: Zen 1의 192 엔트리에서 Zen 4의 320, Zen 5의 448으로 꾸준히 증가하여, 더 넓은 명령어 윈도우에서 ILP를 추출합니다. 정수 레지스터 파일도 240 엔트리(64비트), FP 레지스터 파일은 384 엔트리(512비트)로 확장되었습니다.
🔧 10.2 Intel Lion Cove (2024) — Nehalem 이후 최대 변화
Intel의 Lion Cove P-core(Lunar Lake/Arrow Lake)는 Redwood Cove 대비 14% IPC 향상을 달성했으며, Nehalem(2008) 이후 가장 큰 아키텍처 변화로 평가됩니다.
분할 스케줄러(Split Scheduler): 기존의 통합 스케줄러를 정수(144-entry, 6 포트) + 벡터(96-entry, 5 포트)로 분리했습니다. 이 설계는 정수와 벡터 연산 간의 스케줄링 충돌을 40% 감소시켰습니다.
3-레벨 데이터 캐시: 기존 L1을 L0(48KB)로 재명명하고, 새로운 192KB 중간 계층(기존 L1과 L2 사이)을 추가했습니다. 이를 통해 평균 load-to-use 시간이 단축되어 IPC가 향상되었습니다. L2는 Arrow Lake에서 3MB로 증가했습니다.
Hyper-Threading 제거: 하이브리드 아키텍처(P-core + E-core) 환경에서 스레드 병렬 워크로드는 E-core가 담당하므로, HT를 제거하여 15% 성능 효율 향상, 10% 면적당 성능 향상, 30% 전력당 면적당 성능 향상을 달성했습니다. ROB는 576 엔트리, 디코드 폭은 8-wide, 리타이어 폭은 12-wide로 확장했습니다.
🍎 10.3 Apple M4 (2024) — ARM 기반 ILP의 정점
Apple의 M4 P-core(3세대 Sawtooth)는 ARM 아키텍처 기반으로 가장 넓은 OoO 윈도우를 가진 것으로 알려져 있습니다. M4는 TSMC N3E(3nm Enhanced) 공정으로 제조되며, 28억 개의 트랜지스터를 탑재합니다.
OoO 윈도우가 약 ~630 엔트리로 측정되어, x86과 ARM을 통틀어 가장 큰 규모입니다. ALU 유닛은 8개로 확장되었으며, 9-wide 디코드를 지원합니다. 이러한 대규모 백엔드 덕분에, 동일 클럭에서 x86 프로세서를 능가하는 단일 스레드 IPC를 달성합니다.
🔐 10.4 Spectre/Meltdown — 투기적 실행의 보안 대가
2018년 발견된 Spectre와 Meltdown은 투기적 실행이 만든 가장 심각한 보안 위협입니다. 투기적 실행 중 접근한 데이터가 캐시에 흔적(사이드 채널)을 남기고, 공격자가 이를 타이밍 공격으로 추출하여 커널 메모리, 암호화 키 등 민감한 정보를 유출할 수 있습니다.
| 취약점 | 메커니즘 | 영향 범위 | 주요 완화 기법 |
|---|---|---|---|
| Meltdown (V3) | 투기적 실행 중 커널 메모리 읽기 | 주로 Intel CPU | KPTI (커널 페이지 테이블 격리) |
| Spectre V1 | 경계 검사 우회 (조건 분기 오예측 이용) | Intel, AMD, ARM 전반 | 소프트웨어 패치, 배리어 삽입 |
| Spectre V2 | 간접 분기 타겟 주입 (BTB 오염) | Intel, AMD, ARM 전반 | Retpoline, eIBRS, IBPB |
| BPRC (2025) | 분기 예측기 비동기 업데이트 경합 조건 | Intel 9세대~14세대 | 마이크로코드 업데이트 (1~3% 성능 감소) |
2025년 5월에도 ETH Zurich 연구자들이 BPRC(Branch Prediction Race Conditions)라는 새로운 Spectre 변종을 발견했습니다. Intel의 분기 예측기가 파이프라인 내에서 비동기적으로 업데이트되어 경합 조건이 발생하는 것입니다. Intel은 2025년 1월에 이미 대응 마이크로코드를 배포했으며, 대부분의 프로세서에서 1~3%의 성능 영향만 발생합니다.
이러한 보안 위협은 투기적 실행 설계에 근본적인 영향을 미치고 있습니다. Intel의 Lion Cove에서 Hyper-Threading을 제거한 것도 보안 복잡도 감소라는 측면이 있으며, 현대 프로세서는 분기 예측기의 권한 수준 분리, 추측적 메모리 접근의 추가 검증 등 성능과 보안의 균형을 끊임없이 조율하고 있습니다.
📊 10.5 ROB 크기 진화 (2010~2026)
| 프로세서 | 연도 | ROB/OoO Window | 발행 폭 | 디코드 폭 |
|---|---|---|---|---|
| Intel Nehalem (교재 기준) | 2008 | 128 | 4-wide | 4-wide |
| Intel Sandy Bridge | 2011 | 168 | 6-wide | 4-wide |
| AMD Zen 1 | 2017 | 192 | 6-wide | 4-wide |
| Intel Golden Cove | 2021 | 512 | 6-wide | 6-wide |
| AMD Zen 4 | 2022 | 320 | 6-wide | 4-wide |
| Apple M3/M4 P-core | 2023/24 | ~630 | ~8-wide | 9-wide |
| AMD Zen 5 | 2024 | 448 | 8-wide (INT rename) | 2×4-wide |
| Intel Lion Cove | 2024 | 576 | 분할 스케줄러 | 8-wide |
교재의 Nehalem(128 ROB)에서 2024년 Lion Cove(576 ROB)까지 약 4.5배 증가했습니다. 이는 ILP 한계론에도 불구하고, 제조 공정 미세화와 전력 효율 개선이 계속되면서 프로세서 설계자들이 여전히 더 넓은 OoO 윈도우를 추구하고 있음을 보여줍니다.
📋 11. 핵심 정리 & 결론
1️⃣ 의존성 = ILP의 근본 장벽. RAW(진정한 의존성)는 포워딩으로 완화. WAR/WAW(이름 의존성)는 레지스터 재명명으로 완전 제거. 제어 의존성은 분기 예측으로 해결.
2️⃣ Tomasulo 알고리즘 = 현대 OoO의 원조. 예약역 + 레지스터 재명명 + CDB 브로드캐스트. 1967년 IBM 360/91에서 시작, 1990년대부터 모든 고성능 CPU가 채택.
3️⃣ ROB = 투기적 실행의 핵심. 비순차 실행 + 순차 커밋으로 정밀 예외 보장. 예측 실패 시 안전한 롤백 가능.
4️⃣ 분기 예측 정확도가 ILP의 열쇠. 99%+ 정확도를 위해 토너먼트 예측기, TAGE, 신경망 기반 예측기 등 계속 진화.
5️⃣ ILP의 한계 → 멀티코어 + 멀티스레딩 전환. 전력 장벽과 복잡도 한계로 단일 코어 IPC ~6이 실질적 상한. TLP(Chapter 5)와 DLP(Chapter 4)로 확장.
6️⃣ 2026년: ILP는 죽지 않았다. Zen 5(ROB 448), Lion Cove(ROB 576), Apple M4(~630)가 보여주듯, 각 코어 내부의 ILP 투자는 계속되고 있으며, 보안(Spectre/Meltdown)과의 균형이 새로운 과제.
댓글
댓글 쓰기