Join the conversation

Join the community of Machine Learners and AI enthusiasts.

Sign Up
SeaWolf-AIΒ 
posted an update 3 days ago
Post
3937
πŸ“± POCKET β€” a 35-billion-parameter model that runs on your iPhone, and on your PC with no GPU

We're releasing POCKET, VIDRAFT's flagship Darwin-36B-Opus compressed for on-device use. No fork, no CUDA, no cloud β€” it runs on stock llama.cpp. It's a sparse Mixture-of-Experts model (256 experts, only 8 active per token), so the file can be large while the work per token stays small. That's what lets a 35B model run on a phone, and generate fast on a CPU with no graphics card.

Measured (POCKET-35B IQ1_M vs Bonsai-27B Q1_0):
β€’ CPU generate (Xeon, 16 threads): 27.0 vs 10.1 tok/s β†’ 2.69Γ— faster
β€’ GPU generate (H100): 197 vs 89 tok/s β†’ 2.22Γ— faster
β€’ GPU prompt processing (H100): 753 vs 1816 β†’ 0.41Γ— (Bonsai wins this one β€” MoE prefill wakes every expert, so sparsity stops helping there. We say so.)
β€’ Quality (HellaSwag, 400 q): 61.0% vs 60.0% β†’ a tie (confidence intervals overlap)

On a real consumer laptop β€” MacBook M3 Pro (18 GB) β€” POCKET wins every axis, prompt processing included:
β€’ Metal generate: 25.4 vs 12.8 β†’ 1.99Γ—
β€’ CPU generate: 13.8 vs 4.4 β†’ 3.13Γ—
β€’ Metal prompt: 240.7 vs 73.4 β†’ 3.28Γ—

One more quiet fact: the same-size, quality-oriented rival Ternary-Bonsai-27B (7.2 GB) fails to load in upstream llama.cpp at all β€” it needs the PrismML fork. POCKET runs on the tools you already have: LM Studio, Ollama, PocketPal, MLX.

πŸ“– Full story (tech, measurements, recipes): https://huggingface.co/blog/FINAL-Bench/pocket

Models:
πŸ“¦ POCKET-35B-GGUF (PC / server, no GPU): FINAL-Bench/POCKET-35B-GGUF
πŸ‡°πŸ‡· POCKET-KR-GGUF (Android): FINAL-Bench/POCKET-KR-GGUF
🍎 POCKET-KR-MLX (iPhone / Mac): FINAL-Bench/POCKET-KR-MLX
🌍 POCKET-EN-GGUF (English phone / PC): FINAL-Bench/POCKET-EN-GGUF
πŸ–₯️ Live demo (answering on a CPU, no GPU): FINAL-Bench/POCKET-35B-CPU
πŸ“š Collection: FINAL-Bench/pocket-models-6a618ee5d23eafb7e185a5c6

The prefill number is the one that actually matters, and it flips depending on hardware.

On H100, POCKET loses prompt processing 0.41x, MoE prefill wakes every expert so sparsity buys nothing there. But on the M3 Pro, POCKET wins prompt processing too, 3.28x. Same architecture, opposite verdict, depending only on where it runs.

Is that Metal handling sparse-expert prefill differently than H100's batched prefill, or is the H100 loss really about batch size, the dense model gets to batch prefill and Metal single-stream doesn't?

Β·

Great question, thanks for digging into this πŸ™ Your hypothesis β‘‘(batch size) is essentially right.

The H100 prefill loss isn't really an inherent MoE limitation β€” it's a batching/GEMM-efficiency effect. A dense model packs its large-batch prefill into one big GEMM and saturates the tensor cores, while an MoE scatters tokens across experts into many small GEMMs with lower utilization. So in that regime, dense wins.

On the M3 Pro (Metal, single-stream), that "big-batch advantage" mostly isn't there β€” it's memory-bandwidth bound. What actually matters there is active params per token, so the sparse POCKET comes out ahead on prefill too.

So it's not that Metal does something special with sparse prefill β€” it's that the batch advantage dense enjoys on the H100 disappears on-device, exactly as you suspected. And since POCKET is built for that on-device regime (phone/laptop), we consider those the numbers that actually matter for its use case. Really appreciate the sharp observation! πŸ™Œ

Good, that confirms it: the H100 loss is a batching artifact, not an MoE tax. Dense wins when there's a fat batch to fill big GEMMs, sparse wins when there isn't and it's bandwidth-bound instead.

That reframes what POCKET's numbers are actually claiming: bandwidth-bound single-stream is the regime that matters for on-device, H100 batched prefill was never the right comparison to lead with.

Does the memory-bandwidth advantage hold on other on-device runtimes too, ANE, Snapdragon NPU, or is Metal's single-stream execution doing something specific that a different phone chip's inference stack wouldn't replicate?

Β·

Yeah, that's the right read. It's not really a Metal thing, it's just the regime. Any single-stream, batch=1 decode is memory-bound, and since the MoE only touches its active experts each token, it moves fewer bytes per token and comes out ahead. CPU, Metal, Adreno, whatever β€” as long as you're bandwidth-bound instead of filling a fat batch, sparsity wins. Metal's not doing anything special, it just happens to be one of those backends.

The NPUs are where it gets fuzzy though. Two things: first, they're usually not even in the decode path. Our iPhone build runs through MLX on the GPU, not the ANE, and Snapdragon llama.cpp mostly leans on CPU/GPU too, so the NPU is basically sitting idle while the bandwidth-bound units do the work. Second, even if you did route to them, dynamic MoE is a bad fit β€” ANE and Hexagon want static dense matmul graphs, and per-token, data-dependent expert gather is exactly the thing they're bad at. You'd need a routing-aware compile path and that doesn't really exist yet.

So short version: it carries across bandwidth-bound on-device runtimes, but I wouldn't bet on it transferring to the NPUs as-is. And to be upfront, we've actually measured CPU and Metal β€” the ANE/Hexagon part is me reasoning from how those chips work, not something we've benchmarked. Efficient dynamic MoE on mobile NPUs is still kind of an open problem, and honestly a fun one.

That's the honest kind of answer, the measured-vs-reasoned line called out explicitly matters more than the number itself.

The real blocker isn't bandwidth, it's the compile contract. NPU compilers want one fixed dataflow graph, and per-token top-k routing breaks that contract every single token.

Is there a known partial fix, like sorting tokens by expert before the NPU pass so each pass through it looks static again, or does the routing itself need to become predictable (fixed groups, not per-token top-k) before an NPU compiler could even start on this?