Diagram

The three acronyms get thrown around like they’re interchangeable. They’re not. An APU is an architectural decision about memory and die integration. A GPU is a parallel compute engine. An NPU is a matrix-multiply accelerator. Understanding the difference means understanding why your Ryzen laptop doesn’t need an external GPU, why Apple’s M-series chips run circles around Intel in AI workloads, and why AMD puts a tiny RISC-V core inside your display controller.

This post goes to the silicon level.


The GPU — a parallel machine that happened to render triangles

Diagram

A modern discrete GPU like the Radeon RX 7900 XT contains thousands of arithmetic logic units organized into Compute Units. Each CU has 64 stream processors that execute the same instruction on different data — the SIMD (Single Instruction, Multiple Data) model. This is why GPUs are good at shaders, matrix multiplication, and anything embarrassingly parallel.

The bottleneck is not compute — it’s memory. A discrete GPU has its own pool of high-bandwidth VRAM (GDDR6 or HBM) that sits on a separate card. To get data from the CPU to the GPU, you have to:

  1. Allocate CPU-side memory and fill it with data
  2. Allocate GPU-side VRAM through the driver
  3. DMA-transfer the data across the PCIe bus
  4. Execute the kernel
  5. DMA-transfer results back

A PCIe 4.0 ×16 link maxes out at ~32 GB/s. Meanwhile, the GPU’s internal VRAM bandwidth is 800 GB/s. The PCIe link is 25× slower. Every frame rendered, every matrix multiplied — the data has to cross this bridge. This is why discrete GPUs have massive local VRAM: to minimize how often they touch the PCIe bus.


The APU — kill the bus, share the memory

Diagram

An APU (Accelerated Processing Unit — AMD’s term; Intel calls it “processor graphics”) places the CPU cores and GPU cores on the same physical die, connected by a high-speed coherent fabric instead of an external PCIe bus.

The critical difference is the memory model:

Architecture CPU memory GPU memory Transfer mechanism Latency
discrete GPU System DDR Local VRAM PCIe DMA copy microseconds
APU Unified DDR Unified DDR Pointer pass nanoseconds

With an APU, the CPU and GPU share a single physical address space. When the GPU needs data, the CPU doesn’t copy it — it passes a pointer. The GPU’s memory controller can access any page in system RAM directly through the Infinity Fabric. This eliminates the PCIe round-trip entirely.

The trade-off: shared bandwidth. In a discrete GPU, the GPU has dedicated 800 GB/s GDDR6 pipes. In an APU, CPU and GPU compete for the same dual-channel DDR4 link at ~51 GB/s. The GPU gets less raw bandwidth, but it gains zero-copy access to CPU data structures. For laptop workloads — browser rendering, video decode, desktop compositing — the latency win from pointer-passing outweighs the bandwidth loss.

The Infinity Fabric in detail

Diagram

On a Ryzen APU, the Infinity Fabric operates as a cache-coherent interconnect using the MOESI protocol (Modified, Owned, Exclusive, Shared, Invalid). Both the CPU and GPU participate in the same coherence domain. When the GPU writes to a cache line that the CPU has cached, the fabric automatically invalidates the CPU’s copy. No driver intervention, no explicit flush — hardware maintains coherence at line granularity.

This is what makes zero-copy buffer sharing possible in practice. The amdgpu kernel driver can map GPU-accessible buffers directly into userspace via the Graphics Address Remapping Table (GART), and those same physical pages are accessible to the CPU through its regular page tables. The GPU’s IOMMU context ensures that GPU memory accesses go through the same translation layer as CPU accesses.

The bandwidth reality

Diagram

The bandwidth comparison is nuanced: - Discrete GPU VRAM: 800 GB/s — pure win for shader-heavy workloads - Discrete GPU → CPU: 32 GB/s — the bottleneck for ML inference and data-intensive compute - APU unified memory: 51 GB/s shared — less peak than VRAM, but more effective bandwidth for CPU→GPU data flow because there’s no copy

For a 7B-parameter LLM running inference, the model weights are ~14 GB in FP16. On a discrete GPU, loading the model means a 14 GB PCIe transfer at 32 GB/s = ~0.4 seconds just for the initial load. On an APU with 32 GB of shared DDR4, the weights can be mapped directly from disk to GPU-accessible pages — the CPU never touches them.


The NPU — when matrix multiply gets its own silicon

Diagram

An NPU is not a GPU. It’s a systolic array — a fixed grid of multiply-accumulate (MAC) units where data pulses through in synchronized waves. Think of it as the systolic contraction of a heart: data enters from the left and top edges of the array, flows through the grid one cell at a time, and partial sums ripple through to the output.

The key differences from a GPU:

Property GPU (SIMD) NPU (Systolic Array)
Compute model Same instruction, different data Same operation, flowing data
Precision FP32, FP16, BF16, INT8 INT8, INT4 (sometimes FP16)
Memory External VRAM via memory controller On-die SRAM scratchpad
Programmability General shader programs Fixed operation graph
Peak throughput 10-60 TFLOPS (FP16) 10-50 TOPS (INT8)
Power per op ~0.5-2 pJ ~0.05-0.2 pJ

The systolic array architecture eliminates three things that cost power in a GPU:

  1. Instruction fetch and decode — the NPU doesn’t run a program. The operation graph is compiled ahead of time and the array just executes.
  2. Register file access — data stays in flight within the array. No register reads/writes.
  3. External memory traffic — the scratchpad SRAM is on-die, accessed at L1 cache speeds (~1 TB/s per bank), not external DRAM.

A 16×16 systolic array running at 2 GHz with INT8 precision delivers 16 × 16 × 2 GHz × 2 ops/MAC = 1.024 TOPS for that single array. Stack multiple arrays and you hit 40+ TOPS at a fraction of the power of a GPU achieving the same throughput.

The dataflow pattern

Diagram

The systolic array processes a matrix multiply in 2N cycles for an NxN array: N cycles to fill the pipeline and N cycles to drain it. Once the pipeline is full, every cell produces a result every cycle. There is no instruction overhead, no branch prediction, no cache miss — just synchronized data movement.

This is why NPUs claim 10× better energy efficiency than GPUs for inference. Not because the silicon is magically better — because they eliminated the von Neumann bottleneck. There is no instruction stream to fetch, no program counter to advance, no register file to index. The computation is the dataflow.


The modern SoC — all four on one piece of silicon

Modern laptop SoCs (AMD Strix Point, Intel Lunar Lake, Apple M4) integrate all four compute paradigms on a single die connected by a coherent fabric:

Block What it does Example silicon
CPU Serial, branch-heavy, OS kernel, browser JS Zen 5 / Lion Cove / Apple P-core
GPU Parallel floating-point, graphics, compute shaders RDNA 3.5 / Xe2 / Apple GPU
NPU INT8/INT4 matrix multiply (AI inference) XDNA 2 / Intel NPU 4 / Apple ANE
Media Engine Fixed-function video encode/decode VCN 4.0 / Intel QuickSync / Apple Media Engine

The coherent fabric means every block sees the same memory. The NPU can operate on data produced by the GPU without a copy. The CPU can inspect NPU output without a DMA transfer. The media engine can write decoded frames directly into GPU-accessible buffers.

This is the endgame of the APU concept: not just CPU+GPU, but every specialized compute engine sharing a single unified memory pool through a cache-coherent interconnect.


Programming models — how you talk to each one

Diagram

Each compute engine has a fundamentally different programming model:

Engine Model Abstraction Example
CPU Imperative, threads C ABI, OS scheduler gcc -O3 -march=native
GPU Data-parallel kernels API (Vulkan/CUDA), driver compiles to ISA vkCmdDispatch(cmd_buf, groups_x, groups_y, 1)
NPU Graph execution Model compiler (ONNX → NPU bytecode) session.Run(graph, inputs, outputs)

The GPU model requires the programmer to manage memory explicitly: allocate buffers, record command buffers, insert pipeline barriers, submit to queues, synchronize with fences. The NPU model is declarative: you describe the computation as a directed acyclic graph (DAG) of tensor operations, and the compiler maps it onto the systolic array. You never write a “shader” for an NPU — you write a model.


Concrete silicon comparisons

Diagram
Chip CPU GPU NPU Memory Power NPU TOPS
Ryzen 7 7730U 8C/16T Zen 3 8 CU RDNA 2 DDR4-3200 shared 15-28W 0 (GPU only)
Ryzen AI 9 HX 370 12C/24T Zen 5 16 CU RDNA 3.5 XDNA 2 LPDDR5x-7500 shared 15-54W 50
Apple M4 10C (4P+6E) 10C Apple GPU ANE 16-core LPDDR5x unified 10-22W 38
Core Ultra 7 258V 8C (4P+4E) 8 Xe2 CUs NPU 4 LPDDR5x-8533 shared 8-30W 48
RTX 4060 Laptop — (needs host) 3072 CUDA + 96 Tensor — (tensor cores) 8 GB GDDR6 dedicated 35-115W 116 (FP16)

The discrete NVIDIA GPU still wins in raw throughput — 116 TOPS from tensor cores — but at 3-10× the power draw. For a laptop that runs on battery, the integrated NPU in Strix Point or Lunar Lake delivers better TOPS per watt because it doesn’t pay the PCIe tax.


What runs where — a practical map

In a modern SoC, real workloads don’t run on one engine — they chain across all of them:

  1. Media Engine decodes a 4K AV1 video stream from YouTube into a GPU-accessible buffer
  2. NPU runs a real-time super-resolution model on the decoded frames (upscaling 1080p → 4K)
  3. GPU composites the upscaled frames with browser UI overlays using compute shaders
  4. Display Engine scans out the final framebuffer to the panel at 120 Hz

None of these stages involve a memory copy. Each block reads from and writes to the same unified memory pool through the coherent fabric. This pipeline would require four PCIe round-trips on a discrete GPU system. On an SoC, it’s four fabric transactions at L3 cache latency.


The bits you actually care about

After all the architecture, the practical summary:

If you… You want… Because…
Browse the web, compile, use a terminal Any APU CPU-limited, GPU just composites
Play games at 1440p high settings Discrete GPU Need 800 GB/s VRAM bandwidth
Run local LLMs (7B-13B) SoC with NPU NPU inference, unified memory avoids weight copies
Train ML models Discrete GPU (NVIDIA) CUDA, FP16 tensor cores, 24 GB+ VRAM
Develop GPU compute (Vulkan, HIP) | Discrete GPU | Tooling, profiling, debuggability |
Edit 4K video | SoC with Media Engine | Hardware encode/decode at 10× real-time |
Build a thin Linux laptop | APU (AMD/Intel) | Single die, one heatsink, simple drivers |

My Ryzen 7 7730U is a pure APU — no NPU, 8 RDNA 2 CUs. It runs my terminal, browser, and Clojure REPL perfectly. When I need LLM inference, I use the cloud. When I need to understand the GPU at the driver level, the APU’s simpler memory model (no VRAM, no PCIe) actually makes it easier to debug and profile than a discrete card. The amdgpu driver’s GART and IOMMU integration are cleaner to reason about when there’s only one memory pool.


Hardware referenced: AMD Ryzen 7 7730U (Barcelo), AMD Ryzen AI 9 HX 370 (Strix Point), Intel Core Ultra 7 258V (Lunar Lake), Apple M4, NVIDIA RTX 4060 Laptop. Kernel: linux-cachyos 7.1.6, amdgpu driver.