<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Prasad Khake — Writing</title><description>Notes on making LLMs run well on-device — MLX, Apple Silicon, tokenizers, and the seams where models meet real hardware.</description><link>https://prasadkhake.com/</link><language>en-us</language><item><title>At 32,000 tokens, the costliest thing my MacBook did was wait seven minutes to speak</title><link>https://prasadkhake.com/blog/kv-cache-tax-m3-vs-l4/</link><guid isPermaLink="true">https://prasadkhake.com/blog/kv-cache-tax-m3-vs-l4/</guid><description>I ran the same long-context test on a 16 GB fanless M3 and a ₹23 rented NVIDIA L4. The laptop fits a 32k context on an 8B model and keeps every planted fact — but prefill balloons to seven minutes and its decode speed can&apos;t even be measured, because the fanless chip throttles. A measured, cross-hardware look at the KV-cache tax.</description><pubDate>Wed, 08 Jul 2026 00:00:00 GMT</pubDate></item><item><title>Learning fine-tuning by building a tool-calling LoRA on an M3</title><link>https://prasadkhake.com/blog/lora-tool-calling-m3/</link><guid isPermaLink="true">https://prasadkhake.com/blog/lora-tool-calling-m3/</guid><description>The applied chapter of a from-scratch project: after building tokenization, attention, gradient descent, a tiny GPT, and LoRA by hand, I ran a real QLoRA fine-tune — teaching Llama-3.2-1B to call tools on a MacBook, then measuring honestly what changed and what the adapter costs at inference. A 2.8M-parameter adapter (0.23% of the model) clearly helped on a small test; the debugging taught me the most.</description><pubDate>Tue, 07 Jul 2026 00:00:00 GMT</pubDate></item><item><title>When to hand-write a GPU kernel on Apple Silicon (and when the compiler already won)</title><link>https://prasadkhake.com/blog/metal-kernels-from-scratch/</link><guid isPermaLink="true">https://prasadkhake.com/blog/metal-kernels-from-scratch/</guid><description>I wrote five GPU kernels from scratch on a 16 GB M3 to learn how LLM inference works at the metal. The most useful thing wasn&apos;t a kernel — it&apos;s a decision rule: never hand-write elementwise ops (the compiler already fuses them), reach for a kernel the moment a reduction appears, and remember the famous trick is rarely the hard part.</description><pubDate>Tue, 30 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Atomic Chat&apos;s TurboQuant headline did not survive a chat-generation benchmark on my M3</title><link>https://prasadkhake.com/blog/atomic-turboquant-m3/</link><guid isPermaLink="true">https://prasadkhake.com/blog/atomic-turboquant-m3/</guid><description>Atomic Chat advertises TurboQuant as 8x faster inference and 6x less memory. I tested the local MLX TurboQuant KV path on a 16 GB M3. It saved about 3-5% total peak memory and did not speed up generation — a useful reminder that KV-cache microbenchmarks do not automatically become whole-chat product claims.</description><pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate></item><item><title>I built self-speculative decoding for MLX. On an M3, naive layer-skip never beats baseline — 24 configs, 24 losses</title><link>https://prasadkhake.com/blog/self-spec-mlx-m3/</link><guid isPermaLink="true">https://prasadkhake.com/blog/self-spec-mlx-m3/</guid><description>Self-speculative decoding lets a model draft its own tokens by skipping layers — speculative decoding&apos;s speedup with no extra memory. I built it for MLX and swept 24 configs on an M3. Every one was slower than baseline, even though all were lossless. Here&apos;s why, and the paper that fixes it.</description><pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Three ways to make an LLM read its weights less often on a Mac — and why each one backfires</title><link>https://prasadkhake.com/blog/three-ways-fewer-weight-reads-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/three-ways-fewer-weight-reads-mac/</guid><description>Single-stream decoding on Apple Silicon is bottlenecked by reading the model&apos;s weights out of memory, not by the math. Three techniques attack that directly — speculative decoding, diffusion generation, and self-speculative layer-skipping. I measured all three on a 16 GB M3. Each is right in theory and backfires in its own way: the bottleneck just moves one step further from the arithmetic.</description><pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate></item><item><title>I expected a diffusion LLM to be fast on my Mac. It tied the best model on quality instead — and lost on speed.</title><link>https://prasadkhake.com/blog/diffusion-llm-16gb-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/diffusion-llm-16gb-mac/</guid><description>LLaDA2.0-mini, a diffusion language model, runs on a 16 GB M3 and ties Qwen3-4B for the best answer-quality score I&apos;ve measured (20/21). But it&apos;s slower than the fastest autoregressive model and uses 4× the memory of the lightest — and the exact reason I expected it to be fast on bandwidth-bound hardware turned out to be why it isn&apos;t. A measured look at where the bottleneck actually moved.</description><pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Apple&apos;s on-device model ties a 4-bit Llama-3.1-8B — and won&apos;t name the M1</title><link>https://prasadkhake.com/blog/apple-on-device-model-benchmark/</link><guid isPermaLink="true">https://prasadkhake.com/blog/apple-on-device-model-benchmark/</guid><description>Apple shipped an official Python SDK for its on-device Foundation Model at WWDC 2026. I put the ~3B model through the same 21-task quality suite I use for MLX models: it ties a 4-bit Llama-3.1-8B (18/21), one question behind Qwen3-4B. Quality is the only fair axis to compare — and that limitation is itself the interesting part.</description><pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate></item><item><title>I turned on MLX&apos;s memory-saving flag and ran out of memory</title><link>https://prasadkhake.com/blog/kv-bits-memory-flag-backfires/</link><guid isPermaLink="true">https://prasadkhake.com/blog/kv-bits-memory-flag-backfires/</guid><description>On a 16 GB Mac, MLX&apos;s --kv-bits flag — whose entire job is to shrink the KV cache so longer contexts fit — raised peak memory at every context length I tested, and OOM&apos;d at 32K where plain fp16 fit at 9.4 GB. It&apos;s also no faster (8-bit decoding ran ~4× slower in my tests) and costs no quality you&apos;d want to keep. Here&apos;s the measurement, the code-level cause, and why the flag backfires on this path.</description><pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Speculative decoding on a 16 GB Mac: a 20% win that becomes a 25% loss</title><link>https://prasadkhake.com/blog/speculative-decoding-16gb-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/speculative-decoding-16gb-mac/</guid><description>A 1B draft model speeds up Llama-3.1-8B by 20% on an M3 — at num_draft_tokens=2. Push that dial to 4 and decoding gets 25% SLOWER than using no draft at all. Here&apos;s the measured curve, and why low draft counts win when decode is bound by memory bandwidth.</description><pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Gemma 4 on a 16 GB Mac: the E4B matches the 12B at 42% less RAM and 3× the speed</title><link>https://prasadkhake.com/blog/gemma-4-qat-on-m3/</link><guid isPermaLink="true">https://prasadkhake.com/blog/gemma-4-qat-on-m3/</guid><description>Google&apos;s Gemma-4 E4B posts the same math and factual scores as the full 12B on an M3 MacBook Air — in 6.6 GB instead of 11.4, at 8.2 tok/s instead of 2.7 — so on a 16 GB Mac the E4B is the one to run. This is a size win, not a QAT one: the 12B&apos;s own QAT build doesn&apos;t shrink or speed it up. Honest numbers, measured under a real 2048-token load.</description><pubDate>Mon, 08 Jun 2026 00:00:00 GMT</pubDate></item><item><title>My benchmark graded &apos;7! = 5040&apos; as wrong — and two other ways it lied to me</title><link>https://prasadkhake.com/blog/benchmark-bugs-that-inflated-my-scores/</link><guid isPermaLink="true">https://prasadkhake.com/blog/benchmark-bugs-that-inflated-my-scores/</guid><description>Re-running my own LLM benchmark, I found a bug that had inflated the quality scores in posts I&apos;d already published. Then a second bug. Then a third. Here&apos;s how a wrong number looks exactly like a right one — and why you spot-check the failures, not the passes.</description><pubDate>Sun, 07 Jun 2026 00:00:00 GMT</pubDate></item><item><title>One flag makes Qwen3-4B beat Llama-3.1-8B on a 16 GB Mac — at half the RAM</title><link>https://prasadkhake.com/blog/qwen3-4b-thinking-flag-16gb-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/qwen3-4b-thinking-flag-16gb-mac/</guid><description>On an M3 MacBook Air, Qwen3-4B with the thinking trace turned off scores 20/21 on a verifiable suite — beating Llama-3.1-8B&apos;s 18/21 at half the memory and nearly double the speed. With thinking on, the same model drops to 7/21. The flag is enable_thinking=False, and here&apos;s exactly what it changes and why it matters.</description><pubDate>Sat, 06 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Gemma 4 12B on a 16 GB Mac: 11 GB RAM, 2.7 tok/s, and what my benchmark got wrong</title><link>https://prasadkhake.com/blog/gemma-4-12b-m3-benchmark/</link><guid isPermaLink="true">https://prasadkhake.com/blog/gemma-4-12b-m3-benchmark/</guid><description>Google&apos;s Gemma 4 12B uses 11.4 GB of RAM and runs at 2.7 tok/s on an M3 MacBook Air — 2.4× the memory of Llama-3.1-8B at well under half the speed. Its math and factual answers are flawless; its coding can&apos;t be cleanly scored. Here&apos;s the honest picture, the multimodal tax, and the benchmark bug I found correcting this post.</description><pubDate>Thu, 04 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Attention sinks: the four tokens that stabilize infinite context on a 16 GB Mac</title><link>https://prasadkhake.com/blog/streamingllm-attention-sinks-16gb-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/streamingllm-attention-sinks-16gb-mac/</guid><description>StreamingLLM (2023) found that keeping four specific tokens in the KV cache prevents catastrophic perplexity collapse at long contexts. mlx-lm implements this as RotatingKVCache(keep=4). Here&apos;s what that means, why it works, and what our measurements on M3 actually show.</description><pubDate>Wed, 03 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Gemma-3-12B QAT vs Qwen3-14B 3-bit: same quality on a 16 GB Mac, but the smaller model runs lighter and faster</title><link>https://prasadkhake.com/blog/gemma-3-12b-vs-qwen3-14b-16gb-mac/</link><guid isPermaLink="true">https://prasadkhake.com/blog/gemma-3-12b-vs-qwen3-14b-16gb-mac/</guid><description>Benchmarking Gemma-3-12B, Qwen3-14B, and Llama-3.1-8B on a 16 GB MacBook Air (M3) with MLX. A quantization-aware 3-bit 12B ties a naïve 3-bit 14B on overall answer quality while running faster and in less memory. On a memory-bound Mac, a well-quantized smaller model can match a bigger naïvely-quantized one — so parameter count alone is the wrong thing to shop on.</description><pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate></item><item><title>What actually runs well on a 16 GB MacBook</title><link>https://prasadkhake.com/blog/16gb-mac-llm/</link><guid isPermaLink="true">https://prasadkhake.com/blog/16gb-mac-llm/</guid><description>Honest local-LLM benchmarks on a base M3, 16 GB — tokens/sec, peak RAM, and exactly where it hits the wall. The numbers nobody publishes because they run on H100s.</description><pubDate>Mon, 01 Jun 2026 00:00:00 GMT</pubDate></item><item><title>Why Mistral and Devstral models drop their spaces on Apple Silicon</title><link>https://prasadkhake.com/blog/mlx-tekken-detokenizer/</link><guid isPermaLink="true">https://prasadkhake.com/blog/mlx-tekken-detokenizer/</guid><description>Debugging why tekken-v13 models emit Ġ instead of spaces through mlx-lm&apos;s server, and the one-line root cause in MLX&apos;s detokenizer routing.</description><pubDate>Sat, 30 May 2026 00:00:00 GMT</pubDate></item></channel></rss>