Skip to content
C.W.K.
Stream
Lesson 01 of 06 · published

Where 819 GB/s Comes From

~15 min · memory, bandwidth, lpddr5, channels, jedec, physics

Level 0Spec-Sheet Skimmer
0 XP0/91 lessons0/19 achievements
0/100 XP to next level100 XP to go0% complete
"819 is not a number Apple chose. It is 6400 times 8 times 16, and then rounded down."

Three Factors

Memory bandwidth is the product of three things, and knowing which is which is most of what this track teaches. Transfer rate, in megatransfers per second (MT/s): how many times per second each data pin changes state. Memory is double-data-rate, so a pin transfers twice per clock cycle; LPDDR5-6400 moves 6,400 million transfers per second on each pin. Width, in bits per transfer: how many pins a channel has. LPDDR channels are narrow — 16 bits each in the LPDDR5 standard — and get ganged together; this quest counts in 64-bit slices (four LPDDR5 channels) because Apple's figures fit that unit exactly. Channel count: how many such slices the package fans out. Multiply, divide by eight for bytes, and you have the number on the spec sheet.

The M3 Ultra: 6,400 MT/s × 8 bytes per 64-bit slice = 51.2 GB/s per slice. Sixteen slices = 819.2 GB/s. Apple prints 819. The M3 Max: eight slices, 409.6, printed as 400. The base M3: two slices, 102.4, printed as 100. The M2 Ultra uses the same memory at the same rate and, by our fit, the same sixteen slices — 819.2 again — and Apple prints 800, which is the one number in the family that rounds by more than a percent. Apple does not publish channel counts; the counts are our inference from the fit, and they fit so exactly that the inference is safe to teach.

The Generations, as Memory Technology

GenerationMemory standard (JEDEC)Transfer rateGB/s per 64-bit sliceSlices, base → Ultra (our fit)Evidence
M1 (base)LPDDR4X4,266 MT/s34.12 (68.3; Apple never published it)physics fit
M1 Pro / Max / UltraLPDDR56,400 MT/s51.24 → 8 → 16 (200 / 400 / 800 printed)vendor GB/s + physics fit
M2, M3LPDDR56,400 MT/s51.22 → 16vendor GB/s + physics fit
M4LPDDR5X7,500 (base) / 8,533 (Pro, Max)60 / 68.32 → 8 (no Ultra)vendor + fit
M5LPDDR5X9,600 MT/s76.82 → 16 (M5 Ultra "1.2TB/s" = 1,228.8)vendor + fit
(next)LPDDR6, JESD209-6 (published 2025-07)10,667–14,400 MT/s reported; SK hynix 10.7 Gbps parts, supply 2H2685–115 at a 64-bit-equivalent slicevendor (JEDEC, SK hynix) + press-attributed rates

Read the table as a history of one number. Between the base M1 and the base M5, the transfer rate went from 4,266 to 9,600 — 2.25x — and that is the entire per-slice gain across five generations (the M1 Pro, Max and Ultra had already moved to LPDDR5-6400, which is why an M1 Ultra and an M3 Ultra print nearly the same number). Every other multiple in the family is a slice count, and the middle tiers move by generation: in the M3 generation this quest measures, Pro is three, Max is eight (six on the smaller Max), Ultra is sixteen; the M4 and M5 Pro fan out four, several Max SKUs six. A base chip and an Ultra of the same generation share a transfer rate and differ by a factor of eight in how many lanes the package fans out. That is why the tiers, not the generations, are where the big bandwidth numbers live (track one), and why the M5 Ultra's 1.2 TB/s is sixteen slices of 9,600 — the same count the M3 Ultra has, at a faster rate.

Spec, Then Achieved

The number this derivation produces is what the memory can deliver. The GPU track measured what a streaming kernel does deliver: 93–97% on the Air, 90–98% on the M3 Max, 92% on the M2 Ultra, 78% on the M3 Ultra. The derivation is right; what a kernel gets out of it depends on the path between GPU and memory controllers, and the widest part gives up the most — a property this quest measures and reports, and cannot explain from user space. Both numbers go on your card, and the physics track's decode ceiling uses the achieved one.

Code

lpddr.py — bandwidth as rate × width × channels, every generation·python
#!/usr/bin/env python3
"""Spec bandwidth from JEDEC transfer rates and inferred 64-bit slice counts.
Apple publishes GB/s and the memory generation; slice counts are OUR FIT."""

SLICE_BYTES = 8                                  # a 64-bit slice = four 16-bit LPDDR5 channels

RATES = {"LPDDR4X-4266": 4266, "LPDDR5-6400": 6400, "LPDDR5X-7500": 7500,
         "LPDDR5X-8533": 8533, "LPDDR5X-9600": 9600, "LPDDR6-10667": 10667, "LPDDR6-14400": 14400}

CHIPS = [   # chip, standard, slices, Apple's printed GB/s (None = not published)
    ("M1",        "LPDDR4X-4266",  2, None),
    ("M1 Max",    "LPDDR5-6400",   8, 400),
    ("M1 Ultra",  "LPDDR5-6400",  16, 800),
    ("M3",        "LPDDR5-6400",   2, 100),
    ("M3 Pro",    "LPDDR5-6400",   3, 150),
    ("M3 Max",    "LPDDR5-6400",   8, 400),
    ("M3 Ultra",  "LPDDR5-6400",  16, 819),
    ("M4",        "LPDDR5X-7500",  2, 120),
    ("M4 Max",    "LPDDR5X-8533",  8, 546),
    ("M5",        "LPDDR5X-9600",  2, 153),
    ("M5 Ultra",  "LPDDR5X-9600", 16, 1229),
]

print(f"{'chip':10} {'memory':14} {'MT/s':>6} {'slices':>6} {'GB/s per slice':>14} {'fit':>7} {'Apple':>6}")
for chip, std, n, printed in CHIPS:
    per = RATES[std] * SLICE_BYTES / 1000
    print(f"{chip:10} {std:14} {RATES[std]:6d} {n:6d} {per:14.1f} {per*n:7.1f} {printed if printed else '—':>6}")

print("\nLPDDR6 at 16 slices:", *(f"{RATES[k]*8*16/1000:.0f} GB/s ({k})" for k in ("LPDDR6-10667", "LPDDR6-14400")))

External links

Exercise

Run lpddr.py and add your Mac's row: its memory standard (from the tech-specs page), the transfer rate, and the slice count that reproduces Apple's figure. Add the spec figure and, from the GPU track, your achieved figure to the card. Then compute what your Mac would deliver with the same slice count on LPDDR6 at 10,667 MT/s — that number is a physics prediction for a machine Apple has not announced, and you should label it that way.
Hint
If the tech-specs page names LPDDR5X without a rate, try 8,533 first for M4 Pro/Max and 9,600 for M5; the slice count that makes the fit land on Apple's printed number is the one. A fit that only works with a fractional slice count means the rate is wrong.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.