Week 7: CPU / GPU / NPU

모두연 Pytorch + NPU 온라인 모임 #7 | 2025-02-12

소개

이번 강의에서는 CPU, GPU, NPU가 아키텍처 수준에서 어떻게 다른지를 살펴봅니다. 단순히 “GPU가 병렬 처리에 좋다”는 수준을 넘어, 프로세서 설계 철학의 차이를 이해하는 것이 목표입니다. Latency hiding이라는 공통 문제를 CPU, GPU, NPU가 각각 어떤 방식으로 접근하는지를 추적하면, 왜 NPU가 GPU와 다른 프로그래밍 모델을 요구하는지 자연스럽게 이해할 수 있습니다.

강의 흐름은 다음과 같습니다. 먼저 프로세서의 기본 구조와 설계 철학을 짚고, Latency와 Throughput 개념을 정리합니다. 이어서 Instruction-level pipelining부터 시작하여 Loop-level pipelining(OOO Processor와 VLIW), 그리고 Thread-level pipelining(Multi-core, GPU, NPU)까지 점진적으로 확장해 나갑니다.

Processor Stack: 개발자에서 Datapath까지

프로세서의 동작을 이해하려면, 개발자가 작성한 코드가 실제 하드웨어에서 실행되기까지 거치는 계층 구조를 먼저 파악해야 합니다.

개발자

Programming Language

Compiler

Instruction Set Architecture

Control Logic

Datapath

이 스택에서 Programming Language와 Compiler는 소프트웨어 영역에 해당하고, ISA(Instruction Set Architecture)와 Control Logic, Datapath는 하드웨어 영역에 해당합니다. 특히 Control Logic과 Datapath를 합쳐서 Microarchitecture라고 부릅니다.

프로세서 설계의 핵심 질문

성능은 궁극적으로 하드웨어(Datapath)에서 결정됩니다. 그러나 하드웨어의 모든 디테일을 개발자에게 노출할 수는 없습니다. 따라서 프로세서 설계의 핵심 질문은 **“어느 단계에서 추상화하여 개발자가 이해할 수 있게 만드는가?”**입니다.

이 질문에 대한 접근 방식은 크게 세 가지로 나뉩니다:

  1. Microarchitecture 최적화 — 하드웨어가 알아서 처리하는 방식입니다. 개발자는 하드웨어의 디테일을 알 필요 없이, Microarchitecture 수준의 최적화에 의존합니다.
  2. Compiler 최적화 — 소프트웨어가 정적으로 처리하는 방식입니다. 컴파일러가 하드웨어의 특성을 파악하여 최적화된 코드를 생성합니다.
  3. Programming Model 제공 — 개발자가 하드웨어의 특성을 고려하여 직접 제어할 수 있도록, 최적화 목적에 맞는 프로그래밍 모델을 제공하는 방식입니다.

이 세 가지 접근 방식의 차이가 바로 CPU, GPU, NPU의 설계 철학 차이로 이어집니다.

무어의 법칙과 ISA/Microarchitecture의 분리

무어의 법칙에 따라 더 많은 하드웨어 컴포넌트를 하나의 칩에 집적할 수 있게 되면서, 하드웨어는 점점 복잡해졌습니다. 그러나 이 복잡한 하드웨어를 모두 소프트웨어에 노출시킬 수는 없었기 때문에, ISA와 Microarchitecture가 분리되는 중요한 전환이 일어났습니다. ISA는 소프트웨어가 바라보는 안정적인 인터페이스로 유지되고, Microarchitecture는 세대마다 자유롭게 변경할 수 있게 된 것입니다.

Latency, Throughput, 그리고 Latency Hiding

프로세서 아키텍처를 이해하는 데 있어 가장 기본이 되는 두 가지 개념은 Latency와 Throughput입니다.

Latency는 하나의 작업을 완료하는 데 걸리는 시간이고, Throughput은 단위 시간당 처리되는 작업의 양입니다. 단일 작업만 처리할 때는 Latency가 Throughput에 직접적인 영향을 줍니다. 그러나 병렬로 여러 작업을 처리할 수 있다면, 개별 작업의 Latency가 길더라도 얼마나 빠르게 새로운 작업을 시작할 수 있는가가 Throughput을 결정합니다. 물론 이를 위해서는 작업 간 의존성이 없어야 동시 처리가 가능합니다.

즉, Latency와 Throughput은 항상 직접적인 연관 관계를 갖지는 않습니다. 이 간극을 활용하는 것이 바로 Latency Hiding이며, 이후 살펴볼 모든 아키텍처 기법의 근본적인 동기가 됩니다.

Instruction-Level Pipelining

Latency Hiding의 가장 기본적인 형태는 명령어 수준의 파이프라이닝입니다.

순차적 실행의 한계

명령어를 순차적으로 수행하면, 각 명령어의 수행 시간이 곧 Latency가 됩니다. 명령어마다 레이턴시가 다를 수 있고, 한 사이클에 끝날 수도 있고 여러 사이클이 걸릴 수도 있습니다. 이 방식에서는 한 명령어가 완전히 끝나야 다음 명령어를 시작할 수 있으므로 Throughput이 제한됩니다.

5-Stage Pipeline

이 문제를 해결하기 위해 등장한 것이 파이프라인 아키텍처입니다. 대표적인 예가 MIPS의 5-Stage Pipeline으로, 명령어 실행을 IF(Instruction Fetch), ID(Instruction Decode), EX(Execute), ME(Memory Access), W(Write Back)의 다섯 단계로 나눕니다.

Cycle123456789
Inst 1IFIDEXMEW
Inst 2IFIDEXMEW
Inst 3IFIDEXMEW
Inst 4IFIDEXMEW
Inst 5IFIDEXMEW

의존성이 없는 명령어들의 경우, 파이프라이닝을 통해 x5 Throughput 향상을 달성할 수 있습니다. 각 명령어의 Latency 자체는 변하지 않지만, 여러 명령어의 실행 단계가 겹치면서 전체 Throughput이 크게 개선되는 것입니다.

Vertical Microcode (Encoding)

일반적인 RISC/CISC 명령어 세트는 Vertical Encoding 방식을 사용합니다. 명령어의 각 비트 역할이 하드웨어 동작에 직접 노출되지 않고, 디코딩을 통해 하드웨어 제어 신호로 펼쳐집니다. 이 방식에서는 파이프라인 아키텍처의 디테일이 소프트웨어에 노출되지 않으므로, 하드웨어가 자체적으로 최적화를 수행할 수 있습니다.

MIPS 5-Stage Pipeline 상세 구조

파이프라인의 상세 구조를 들여다보면, 디코딩된 신호가 레지스터 파일, ALU, 다음 스테이지의 입력으로 분기하는 것을 볼 수 있습니다. 이처럼 ISA만으로는 마이크로아키텍처의 구조를 파악할 수 없으며, 이것이 바로 ISA와 Microarchitecture를 분리한 핵심 이유입니다.

Data Hazard와 Bypass Logic

파이프라이닝에서는 레지스터 간 의존성에 의한 Data Hazard가 발생할 수 있습니다. Data Hazard가 발생하면 파이프라인에 버블(Bubble) 또는 **스톨(Stall)**이 생겨 성능이 저하됩니다. 이를 해결하기 위해 Bypass Logic(Forwarding)이 사용됩니다. 아직 레지스터에 저장되지 않은 데이터를 다음 스테이지로 바로 전달하는 방식인데, 모든 해저드를 항상 해결할 수 있는 것은 아닙니다.

Branch Latency 문제

파이프라인에서 특히 문제가 되는 것은 Branch 명령어입니다. 파이프라인의 첫 단계는 IF(Instruction Fetch)인데, 분기 주소를 알아야 다음에 어떤 명령어를 Fetch할지 결정할 수 있습니다. 그런데 분기 조건과 주소가 결정되는 것은 파이프라인의 후반 단계에서이므로, 그때까지 Fetch를 할 수 없어 Stall이 불가피합니다. Integer program 기준으로 인스트럭션 6~7개 중 하나는 Branch이기 때문에, 이 문제는 성능에 상당한 영향을 미칩니다.

Branch Latency Hiding: Delayed Slot

MIPS 아키텍처에서는 Branch Delay Slot이라는 기법을 사용했습니다. 분기 여부와 관계없이 무조건 실행되는 명령어를 분기 직후에 배치하여, 파이프라인의 빈 슬롯을 활용하는 방식입니다. 그러나 컴파일러가 Delay Slot에 넣을 적절한 Instruction을 찾지 못하는 경우가 있고, Pipeline depth가 늘어나면 Branch Delay도 길어지기 때문에, 현재는 거의 사용되지 않는 기법입니다.

Branch Latency Hiding: Branch Prediction

현대 프로세서에서 Branch Latency를 해결하는 핵심 기법은 Branch Prediction입니다. 분기가 Taken인지 Not Taken인지를 예측하고, **Branch Target Buffer(BTB)**를 통해 분기 대상 주소를 캐싱합니다. 예측이 맞으면 대기 없이 다음 명령어를 Fetch할 수 있지만, 예측이 틀리면 Misprediction이 발생하여 Rollback이 필요합니다. 이처럼 예측에 기반하여 미리 실행을 진행하는 방식을 Speculative Execution이라고 부릅니다.

Loop-Level Pipelining

Instruction-level pipelining이 개별 명령어의 실행 단계를 겹치는 것이었다면, Loop-level pipelining은 한 단계 더 나아가 루프의 서로 다른 iteration을 겹쳐서 실행하는 것입니다.

루프의 순차적 실행 한계

루프에서 조건부 분기(예: BLT)는 루프의 Back Edge를 형성합니다. 이 조건부 분기가 해결되어야 다음 iteration을 수행할 수 있으므로, 기본적으로 루프는 순차적으로 수행될 수밖에 없습니다.

Iteration 중첩을 통한 Latency Hiding

그러나 각 iteration이 서로 다른 데이터를 접근한다면, iteration들을 중첩시켜 Latency Hiding을 하는 것이 가능합니다. 루프 간 의존성이 약하면 파이프라이닝으로 성능을 크게 향상시킬 수 있습니다.

방해요소와 해결책

Loop-level pipelining을 방해하는 두 가지 요소가 있습니다. 첫째는 Control Flow(조건부 분기)이고, 둘째는 서로 다른 iteration의 instruction 사이에 존재하는 False Data Dependency입니다. True Dependency는 값이 계산되고 사용되는 실제 의존 관계인 반면, False Dependency는 저장 공간(레지스터)이 겹쳐서 발생하는 가짜 의존성입니다.

이 문제들의 해결책은 각각 Branch Prediction(Control Flow 해결)과 Register Renaming(False Dependency 해결)입니다.

OOO(Out-Of-Order) Processor: 하드웨어적 접근

Out-of-Order Processor는 하드웨어가 동적으로 Loop-level pipelining 효과를 만들어내는 방식입니다. Sequential code로부터 Branch Prediction을 통해 speculative trace를 생성하고, Register Renaming 후 data-flow graph로 전환합니다. 이렇게 만들어진 data-flow graph에서는 topological order로 병렬 처리가 가능해지며, 최적화 적용도 용이해집니다.

결과적으로 루프가 파이프라인된 형태로 수행되며, 매 cycle 여러 개의 instruction을 동시에 수행하는 효과를 얻습니다. 현재 사용되는 대부분의 CPU(Intel, AMD)는 이 OOO 프로세서 기법을 사용합니다.

Intel Core Architecture의 OOO Engine

Intel Core Architecture의 OOO Engine에서 핵심 역할을 하는 것은 Reorder Buffer입니다. 이것은 Register Renaming과 동적 Data-Flow Graph의 태깅 및 유지를 담당하는 장치입니다.

VLIW: 소프트웨어적 접근

OOO Processor는 동적으로 Data-Flow Graph를 생성하고 관리해야 하므로 매우 복잡한 하드웨어가 필요합니다. Branch Prediction이 실패하면 Rollback이 필요하고, 명령어 윈도우를 키울수록 복구 과정은 더 복잡해집니다. 이러한 문제에 대한 대안으로 등장한 것이 VLIW(Very Long Instruction Word) 아키텍처입니다.

VLIW의 핵심 아이디어는 단순합니다. 하드웨어가 동적으로 만들어내는 효과를, 소프트웨어(컴파일러)가 정적으로 미리 만들어 놓는 것입니다. 소프트웨어적으로 루프를 파이프라인된 형태로 미리 구성하면, 하드웨어는 소프트웨어가 만들어 놓은 파이프라인을 그대로 반복 수행하기만 하면 됩니다. 이렇게 하면 하드웨어가 훨씬 단순해지고, 실행 효율성도 향상될 수 있습니다.

VLIW 아키텍처에서는 여러 Functional Unit이 병렬로 처리 가능한 구조를 갖추고 있으며, 명시적인(Explicit) 병렬 프로그래밍을 수행합니다. 각 사이클마다 하드웨어가 어떤 일을 해야 하는지를 명시적으로 표현하기 때문에, 하드웨어 제어 명령어가 매우 길어져서 “Very Long Instruction Word”라는 이름이 붙었습니다.

Vertical Encoding vs. Horizontal Encoding

VLIW의 명령어 인코딩 방식은 기존 RISC/CISC와 근본적으로 다릅니다.

Vertical Encoding (RISC/CISC)Horizontal Encoding (VLIW)
특징비트들이 인코딩되어 숨겨져 있음HW 구조에 맞춰 명령어가 펼쳐져 있음
동작디코딩 → HW 제어 신호로 펼쳐짐SW가 HW의 각 부분이 어떤 작업을 수행할지 명시적으로 지정

이 두 방식은 계층적으로 결합될 수도 있습니다. 상위 레벨은 Horizontal Encoding으로 전체 구조를 지정하고, 각 단위에서는 Vertical Encoding을 사용하는 방식입니다.

Modular Scheduling: SW Pipelining의 핵심

VLIW 아키텍처에서 소프트웨어 파이프라이닝을 실현하는 핵심 컴파일러 알고리즘은 Iterative Modulo Scheduling입니다. Bob Rau가 1992년 HP Labs에서 발표한 이 알고리즘은, OOO Processor가 하드웨어적으로 수행하는 데이터 플로우 그래프 기반 처리를 컴파일러가 소프트웨어적으로 수행하는 것과 유사한 역할을 합니다.

이 알고리즘은 매우 잘 설계되어 있어, 대부분의 컴파일러가 이 틀을 사용하여 SW Pipelining을 구현하고 있습니다.

Reconfigurable Architecture (Extreme VLIW)

VLIW의 개념을 더 극단적으로 확장하면 Reconfigurable Architecture에 도달합니다. 하드웨어의 다양한 부분을 소프트웨어로 제어하는 것 자체가, 사실상 하드웨어를 재구성(reconfigure)하는 것과 유사하기 때문입니다. 최근 출시되는 많은 NPU들이 바로 이 Reconfigurable Architecture 개념에 맞춰 설계되고 있습니다.

Loop-Level Pipelining 정리

Loop-level pipelining의 핵심은 루프의 iteration을 중첩하여 Latency Hiding을 달성하는 것입니다.

이를 실현하는 두 가지 방식이 있습니다:

  • OOO Processor — 하드웨어가 동적으로 파이프라이닝 효과를 만들어냅니다. 그 이론적 기반은 1960년대의 Tomasulo Algorithm입니다.
  • VLIW Processor — 소프트웨어(컴파일러)가 정적으로 파이프라이닝 효과를 만들어냅니다. 대표적인 알고리즘은 1992년의 Modular Scheduling입니다.

이 두 접근 방식의 대비는 이후 GPU와 NPU의 설계 철학 차이로 직접 연결됩니다.

Thread-Level Pipelining: Multi-Core, GPU, NPU

Instruction-level과 Loop-level pipelining에 이어, 가장 큰 규모의 Latency Hiding은 Thread 수준에서 이루어집니다. 이 전환의 배경에는 CPU 아키텍처의 중요한 변곡점이 있습니다.

CPU의 변곡점: Clock Frequency Scaling의 종료

1990년대는 클럭 속도 향상과 ILP(Instruction-Level Parallelism) 극대화의 황금기였습니다. 그러나 2000년대에 들어서면서 Intel Pentium 4가 과도한 파이프라이닝으로 심각한 발열 문제를 일으키며 대실패를 겪었습니다. 이는 Dennard Scaling의 한계가 현실화된 것으로, Clock Frequency 경쟁이 사실상 종료되는 계기가 되었습니다.

트랜지스터 집적도가 높아질수록 열 밀도가 상승하여 더 이상 클럭 속도를 올리는 것만으로는 성능을 향상시킬 수 없게 되었습니다. 이에 Intel은 ILP 추구에서 Multi-Core + Multi-Threading 방향으로 전략을 전환했습니다. 때마침 인터넷과 서버 시장이 성장하면서, 병렬 처리 프로세서의 중요성이 더욱 부각되었습니다.

Memory Wall 문제

Compute Unit

Interconnect

Compute Unit

Compute Unit

On-Chip Mem

On-Chip Mem

On-Chip Mem

Memory Wall 🧱

DRAM

현대 프로세서에서 가장 큰 성능 병목은 Memory Wall, 즉 오프칩 메모리 접근 속도입니다. 프로세서의 연산 능력은 계속 향상되지만, DRAM에 접근하는 속도는 이를 따라가지 못합니다. 결국 DRAM Bandwidth를 어떻게 최대한 활용하느냐가 프로세서 설계의 핵심 과제가 됩니다.

이 Memory Wall 문제를 가장 효과적으로 해결하는 방법이 바로 Multithreading입니다.

Multithreading을 활용한 Memory Latency Hiding

Multithreading의 핵심 아이디어는 간단합니다. 하나의 스레드가 메모리 접근으로 대기 중일 때, 즉시 다른 스레드를 실행하는 것입니다. 이렇게 하면 메모리 접근의 긴 Latency를 다른 유용한 작업으로 채울 수 있어, 전체 Throughput이 향상됩니다.

GPU: Massive Parallelism으로 Latency를 숨기다

CPU가 Multi-Core로 전환하던 같은 시기인 2000년대에, 그래픽스 프로세서도 큰 변화를 겪고 있었습니다.

Fixed-Function에서 Programmable Device로

GPU는 Fixed-Function 디바이스에서 Programmable Device로 변신했습니다. Shader Programming의 등장이 이 전환의 핵심이었습니다. 이전에는 GPU가 정해진 그래픽스 연산만 수행할 수 있었지만, 이제 개발자가 GPU의 동작을 프로그래밍할 수 있게 된 것입니다.

CPU vs GPU: 설계 철학의 차이

GPU의 설계 철학은 CPU와 근본적으로 다릅니다. GPU는 픽셀이나 삼각형 단위의 Massive Parallelism을 활용하는 데 집중합니다. CPU 대비 Computing Density가 높고 동시 처리 스레드 수가 훨씬 많습니다. 이를 위해 OOO 엔진 등 복잡한 제어 장치를 제거하여 Control을 단순화하고, Throughput 극대화에 집중한 것입니다.

CUDA와 SIMT

2007년 NVIDIA가 발표한 CUDA는 Shader 아키텍처를 소프트웨어가 이해할 수 있는 프로그래밍 모델로 정리한 것입니다. CUDA의 실행 모델은 **SIMT(Single Instruction Multiple Threads)**로, SIMD와 유사하지만 GPU의 메모리 레이턴시 하이딩에 특화되어 있습니다.

SIMT에서는 ThreadBlock과 Warp 개념이 핵심입니다. 하나의 Warp 내 스레드들이 동일한 명령어를 실행하면서, Cache miss가 발생하면 해당 Warp 대신 다른 Warp으로 즉시 switch하여 Latency Hiding을 수행합니다.

GPU: All About Hiding Latency

GPU는 **“All About Hiding Latency”**라고 할 만큼 메모리 레이턴시 문제에 집중하는 아키텍처입니다. 현재 GPU는 2000~2010년 사이에 정의된 아키텍처와 상당히 달라졌고, ML의 특성에 맞게 변모하고 있지만, 초기의 설계 철학은 여전히 유지되고 있습니다.

NVIDIA GPU의 성장과 한계

NVIDIA GPU는 원래 ML을 위해 설계된 것은 아니지만, Massive Parallelism이라는 특성이 ML 워크로드에 매우 적합했습니다. ML 붐과 함께 NVIDIA가 크게 성장하며, 컴퓨팅 성능은 세대마다 급속히 향상되었습니다.

그러나 컴퓨팅 성능의 향상 속도와 메모리 대역폭의 향상 속도 사이의 갭이 점점 벌어지고 있습니다. Blackwell GPU에 이르러서는 성능의 한계점에 도달한 것이 아닌가 하는 논의가 나오고 있으며, DeepSeek 등의 등장으로 스케일업 vs. 효율성에 대한 논의가 활발해지고 있습니다.

GPU의 Multithreading Overhead

GPU의 SIMT 방식이 ML에 완벽하게 적합한지에 대한 의문도 존재합니다. 이에 대해 다음과 같은 논의가 있습니다:

“(1) GPGPU’s multithreading overhead: It is not our intention to lessen GPGPUs’ huge contribution to ML’s recent success… Overhead or not, there were no alternatives, until other options came along”

https://www.sigarch.org/why-the-gpgpu-is-less-efficient-than-the-tpu-for-dnns

최신 GPU는 이러한 기존 한계를 다양한 방법으로 극복하고 있지만, 이 논의는 NPU가 등장하게 된 배경을 이해하는 데 중요한 맥락을 제공합니다.

NPU: 소프트웨어 주도의 Latency Hiding

GPU가 하드웨어적으로 Latency Hiding을 수행한다면, NPU는 소프트웨어적으로 이를 수행합니다. 이 차이는 앞서 살펴본 OOO Processor와 VLIW Processor의 관계와 정확히 같은 패턴입니다.

GPU vs NPU: 핵심 대비

OOO : VLIW = GPU : NPU — 같은 패턴의 HW vs. SW 접근입니다. OOO Processor가 하드웨어적으로 Loop-level pipelining을 달성하는 것처럼 GPU는 하드웨어적으로 Thread-level Latency Hiding을 수행합니다. 반대로 VLIW가 소프트웨어적으로 Loop-level pipelining을 달성하는 것처럼, NPU는 소프트웨어(컴파일러)가 정적으로 전체 실행 계획을 생성합니다.

NPU Architecture: Scratchpad Memory와 DMA

L1 DMA

L1 DMA

L1 DMA

L2 DMA

L2 DMA

L2 DMA

Compute Unit

Interconnect

Compute Unit

Compute Unit

On-Chip Mem
(Scratchpad)

On-Chip Mem
(Scratchpad)

On-Chip Mem
(Scratchpad)

Memory Wall 🧱

DRAM

NPU의 아키텍처에는 GPU와 구별되는 핵심 특징이 있습니다. 온칩 메모리가 캐시가 아닌 Scratchpad Memory이며, 데이터 이동은 DMA로 명시적으로 프로그래밍됩니다. 모든 하드웨어 유닛이 소프트웨어에 노출되어 개별적으로 프로그래밍 가능합니다. GPU에서는 하드웨어가 캐시를 자동으로 관리하고 스레드 스케줄링을 동적으로 처리하는 반면, NPU에서는 이 모든 것을 소프트웨어(컴파일러)가 정적으로 계획합니다.

Horizontal Encoding과 Command Stream

NPU 내부의 하드웨어는 횡적으로 펼쳐져 있으며, 각 유닛이 독립적으로 프로그래밍 가능합니다:

Compute UnitCompute UnitCompute UnitL1 DMAL1 DMAL1 DMAL2 DMAL2 DMAL2 DMA
cmdcmdcmdcmdcmdcmdcmdcmdcmd

Command Stream

Command Processor

Sync Network

Unit 1

Unit 2

...

Unit N

Command Processor가 소프트웨어의 실행 계획을 받아 각 하드웨어 유닛에 분배하고, Sync Network를 통해 서브태스크 간 순서 관계를 유지합니다. 이는 VLIW의 Horizontal Encoding에 가까운 ISA 구조입니다.

NPU Compiler의 역할

NPU에서는 컴파일러의 역할이 GPU에 비해 훨씬 큽니다. 모델을 Graph로 받아들이고, 아키텍처의 디테일을 고려하여 전체 실행 계획을 생성합니다.

GPUNPU
작업 분할HW가 동적으로 처리SW(컴파일러)가 정적으로 처리
스케줄링HW가 스레드 스케줄링컴파일러가 전체 실행 계획 생성
HW 복잡도높음 (스케줄링 로직)낮음 (실행만 담당)
추상화 수준높음 (CUDA)낮음 (HW 디테일 노출)

GPU에서는 하드웨어가 동적으로 작업을 분할하고 스레드를 스케줄링하는 반면, NPU에서는 컴파일러가 이 모든 것을 정적으로 처리합니다. 그 결과 NPU의 하드웨어는 단순하게 실행만 담당하면 되지만, 대신 컴파일러가 하드웨어의 디테일을 깊이 이해하고 최적화된 실행 계획을 생성해야 합니다.

정리

이번 강의에서 다룬 내용을 정리하면 다음과 같습니다.

Memory Wall이 핵심 문제입니다. 현대 프로세서에서 가장 큰 성능 병목은 오프칩 메모리 접근 속도이며, Memory Latency Hiding이 매우 중요합니다. 이는 곧 Memory Bandwidth를 최대한 잘 활용하는 것과 같은 의미입니다.

CPU는 Multi-Core로 전환했습니다. Clock Frequency Scaling의 한계에 도달한 후, Multithreading을 통한 Memory Latency Hiding으로 방향을 전환했습니다.

GPU는 Massive Parallelism으로 Latency를 숨깁니다. CPU보다 훨씬 효율적으로 Multithreading을 활용하며, 원래 Graphics(픽셀, 삼각형)를 위한 Massive Parallelism이 ML 워크로드에도 매우 적합했습니다.

GPU와 NPU의 핵심 차이는 HW vs. SW 접근입니다. GPU는 Vertical Encoding으로 하드웨어의 디테일을 숨기고, 하드웨어가 동적으로 스레드를 스케줄링합니다. 이는 OOO Processor와 유사한 접근입니다. 반면 NPU는 Horizontal Encoding으로 하드웨어의 디테일을 소프트웨어에 노출하고, 컴파일러가 전체 실행 계획을 정적으로 생성합니다. 이는 VLIW(또는 Reconfigurable) Processor와 유사한 접근입니다.

이러한 아키텍처의 차이가 곧 프로그래밍 모델의 차이로 이어지며, 다음 강의에서 다룰 리벨리온 NPU의 구체적인 구현을 이해하는 기반이 됩니다.