<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Llama.cpp on tsvinc</title>
		<link>https://tsvinc.dev/tags/llama.cpp/</link>
		<description>Recent content in Llama.cpp on tsvinc</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Mon, 02 Nov 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://tsvinc.dev/tags/llama.cpp/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Image input on a 27B coder costs 1.1 GiB, once</title>
				<link>https://tsvinc.dev/posts/qwen38-27b-image-input-costs-1-gib/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/qwen38-27b-image-input-costs-1-gib/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve served a GGUF with llama.cpp. &lt;a href=&#34;https://tsvinc.dev/posts/blamed-opencode-flash-next/&#34;&gt;Part 1&lt;/a&gt; introduced the bench.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;I had the memory risk of image input in the wrong place. On a 24 GB RTX 3090 that already holds a 27B coding model with a 128k-token context, I expected the dangerous request to be the full one: an image plus a context filled to the brim. Adding image input to Qwen3.8-27B makes sense: the base model is a vision-language model, and a coding agent that can read a screenshot of a failing UI or a terminal is worth having. The question was whether it still fits on the card.&lt;/p&gt;</description>
			</item>
			<item>
				<title>One open PR made MoE prompts 12-30% faster on my 3090</title>
				<link>https://tsvinc.dev/posts/open-pr-moe-prompts-12-30-faster/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/open-pr-moe-prompts-12-30-faster/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve served a GGUF with llama.cpp. &lt;a href=&#34;https://tsvinc.dev/posts/blamed-opencode-flash-next/&#34;&gt;Part 1&lt;/a&gt; introduced the bench.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;115 upstream llama.cpp commits bought my RTX 3090 at most 2.8%. The next morning, one pull request from outside upstream bought up to 29.7% in prompt speed in &lt;code&gt;llama-bench&lt;/code&gt;, and about 13% through the server that actually feeds the agents, on synthetic prompts. &lt;a href=&#34;https://tsvinc.dev/posts/llamacpp-115-commits-barely-faster/&#34;&gt;Part 25&lt;/a&gt; moved my llama.cpp build forward by those commits and measured the result on the card: prompt reading moved -0.4% to +2.8%, generation 0.0% to +0.6%. I switched anyway, mostly for the parser fixes.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The screenshot opencode never sent</title>
				<link>https://tsvinc.dev/posts/igpu-screenshot-opencode-never-sent/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/igpu-screenshot-opencode-never-sent/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve run a local model behind a coding agent. &lt;a href=&#34;https://tsvinc.dev/posts/igpu-bandwidth-picked-the-model/&#34;&gt;Part 1&lt;/a&gt; has the laptop and its memory pool; the router manual has the serving setup.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tldr&#34;&gt;&#xA;  &lt;span class=&#34;tldr-label&#34;&gt;TL;DR&lt;/span&gt;&#xA;  On a laptop&#39;s integrated Radeon 680M, llama.cpp served 14 model presets (12 models, two of them in two quants) with image input, each with its projector, the small extra file that turns pixels into tokens. On five generated test images they got 54 of 56 single answers right, and read a six-line cut list back with full recall on every model. Mixture-of-experts models with spare GPU memory lost 2% of their generation speed or less; dense 27B models and the presets that already filled the pool lost 4 to 32%. In opencode, a terminal coding agent, versions 1.19.3 and 1.19.5 on my setup and 1.18.35 on a second machine did not send an attached image unless the model entry declared image input: the model got an error string instead, and the run exited 0. Adding &lt;code&gt;&amp;quot;modalities&amp;quot;: {&amp;quot;input&amp;quot;: [&amp;quot;text&amp;quot;, &amp;quot;image&amp;quot;], &amp;quot;output&amp;quot;: [&amp;quot;text&amp;quot;]}&lt;/code&gt; fixed it. One setup that first saw the image arrive without the key had it in a config file in a parent directory, which opencode merges in. An RTX 3090 desktop measured the same projector memory with no speed loss. On the second machine, a Strix Halo mini PC, two models &amp;quot;passed&amp;quot; the image test without seeing the image by running an OCR tool through bash, so check what was sent and what tools ran, not the answer. On 18 questions about real screenshots with thinking on, Gemma 4 26B (a mixture-of-experts model) got 17 at 23 s each on average, and Swift 9B (a dense model) all 18 at 38 s.&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The obvious suspect for anything new on this laptop is the GPU. It&#39;s a Radeon 680M with no memory of its own: on the boot these tests ran on, it borrowed a 4 GiB carve-out plus 13.6 GiB of system RAM it can map (GTT), out of the laptop&#39;s 32 GB, and this series has already spent a fair share of its words on what does and doesn&#39;t fit in it. So the place to expect trouble from letting local coding models look at screenshots is right there: a picture means extra weights, extra tokens and extra memory, on a GPU that has none to spare.&lt;/p&gt;</description>
			</item>
			<item>
				<title>115 llama.cpp commits later, my 3090 was barely faster</title>
				<link>https://tsvinc.dev/posts/llamacpp-115-commits-barely-faster/</link>
				<pubDate>Sun, 01 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/llamacpp-115-commits-barely-faster/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve served a GGUF with llama.cpp. &lt;a href=&#34;https://tsvinc.dev/posts/blamed-opencode-flash-next/&#34;&gt;Part 1&lt;/a&gt; introduced the bench.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;This series is about one 24 GB RTX 3090 and the local models I serve from it as coding agents, each run scored by tests the model never sees. The models are served by llama.cpp, built from source, and since 26 October the build was master at &lt;code&gt;caa8191&lt;/code&gt;. By 31 October upstream was 115 commits further on, and the question was the routine one: did any of them do anything for this card and these models?&lt;/p&gt;</description>
			</item>
			<item>
				<title>Faster prompts, slower agents: a second engine on the 680M</title>
				<link>https://tsvinc.dev/posts/igpu-faster-prompts-slower-agents/</link>
				<pubDate>Sun, 01 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/igpu-faster-prompts-slower-agents/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve run a local model behind a coding agent. &lt;a href=&#34;https://tsvinc.dev/posts/igpu-bandwidth-picked-the-model/&#34;&gt;Part 1&lt;/a&gt; has the laptop and why every model here is a mixture-of-experts; &lt;a href=&#34;https://tsvinc.dev/posts/igpu-agent-runs-none-merge-ready/&#34;&gt;part 2&lt;/a&gt; has how the agent runs were graded.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;tldr&#34;&gt;&#xA;  &lt;span class=&#34;tldr-label&#34;&gt;TL;DR&lt;/span&gt;&#xA;  On a laptop&#39;s integrated Radeon 680M, UnbiasedStrata, an inference engine built around mixture-of-experts models (each token runs through a few expert blocks, a small slice of the parameters), read a 2,048-token prompt 1.4 to 1.5 times as fast as llama.cpp&#39;s Vulkan backend once warm, but only on models whose experts all fit in GPU memory. It generated slower on every model it ran: 52 to 78% of llama.cpp&#39;s speed. Three coding-agent runs on the same model file got the same grades on both engines (2, 3 and 3 out of 5) from part 2&#39;s blind review, which grades the code under a random id. They took longer on Strata: one ran out the two-hour clock, one died on the context limit. Agents spend most of their time generating, so llama.cpp stays the engine for agents on this laptop.&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;The README of UnbiasedStrata closes its human-written note with &amp;quot;Use at your own risk. Works on my machine.&amp;quot; My machine is a 2022 laptop with a Ryzen 7 PRO 6850U and its integrated Radeon 680M GPU, which has no memory of its own and borrows about 16 GB of the laptop&#39;s 30 GB of RAM. It is not the machine the README means. The engine targets an NVIDIA card with CUDA, and the 680M&#39;s chip, gfx1035, appears nowhere in the build&#39;s list of AMD GPUs, not even among the ones marked &amp;quot;unvalidated&amp;quot;. I read the warning, agreed with it, and built the thing anyway.&lt;/p&gt;</description>
			</item>
			<item>
				<title>On a laptop iGPU, memory bandwidth picked the model</title>
				<link>https://tsvinc.dev/posts/igpu-bandwidth-picked-the-model/</link>
				<pubDate>Sat, 31 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/igpu-bandwidth-picked-the-model/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve run a local model behind a coding agent. The &lt;a href=&#34;https://tsvinc.dev/series/3090-agent-bench/&#34;&gt;3090 Agent Bench&lt;/a&gt; ran the same kind of models on a desktop GPU; this series moves them to a laptop.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;I ran local models as coding agents on a laptop: a Ryzen 7 PRO 6850U from 2022, with the models running on its integrated Radeon 680M GPU through llama.cpp. The first request opencode, the coding-agent client I drove them with, sent in a session was 11,000 to 12,400 tokens long, and the model had to read all of it before it wrote a word. A dense 27-billion-parameter model, one that runs every weight for every token, took 299 seconds, about five minutes, to read it. Three mixture-of-experts models of 35 to 40 billion parameters, which route each token through a few expert blocks so that only 2.5 to 3 billion parameters are active, took 77 to 78 seconds. None of them had opened a file of the project yet. Five minutes, and the agent hadn&#39;t done a single thing I could blame it for. That part would have to wait as well.&lt;/p&gt;</description>
			</item>
			<item>
				<title>On one RTX 3090, agent speed followed active parameters</title>
				<link>https://tsvinc.dev/posts/agent-speed-followed-active-parameters/</link>
				<pubDate>Sat, 31 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/agent-speed-followed-active-parameters/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve run a local model behind a coding agent. &lt;a href=&#34;https://tsvinc.dev/posts/blamed-opencode-flash-next/&#34;&gt;Part 1&lt;/a&gt; introduced the bench; this part and the next one sum it up.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;The smallest file on my bench is Ternary Bonsai 2, a 27-billion-parameter model packed into 7.2 GB. Driving a coding agent, it generated 37.9 tokens per second, the median over its three batches of runs. Ornith 1.5, a 35B model in a 19.3 GB file, generated 171.2. The file 2.7 times bigger ran 4.5 times faster.&lt;/p&gt;</description>
			</item>
			<item>
				<title>llama.cpp&#39;s MoE cache wants gigabytes and long prompts</title>
				<link>https://tsvinc.dev/posts/moe-cache-wants-gigabytes/</link>
				<pubDate>Tue, 27 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/moe-cache-wants-gigabytes/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve served a MoE GGUF with llama.cpp and know what &lt;code&gt;--n-cpu-moe&lt;/code&gt; does. The card and the build bump behind these numbers are in &lt;a href=&#34;https://tsvinc.dev/posts/rtx-3090-unlock-what-it-buys/&#34;&gt;The 3090 unlock is real. Where it lands is the catch&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;My agent bench runs local models on one RTX 3090 with 24 GB of VRAM. A mixture-of-experts (MoE) model too big for that can keep part of its experts (blocks of weights, of which each token uses only a few) in system RAM. llama.cpp now has a flag for that case, &lt;code&gt;--moe-cache-mib&lt;/code&gt;: a slice of VRAM that keeps the popular experts on the GPU while the rest sit in RAM. This part measures what it buys on three MoE models: Flint 40B, Ornith 35B and Flash-Next, the last too big even for VRAM and RAM together.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The 3090 unlock is real. Where it lands is the catch</title>
				<link>https://tsvinc.dev/posts/rtx-3090-unlock-what-it-buys/</link>
				<pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/rtx-3090-unlock-what-it-buys/</guid>
				<description>&lt;p&gt;NVIDIA sells the GeForce RTX 3090 with one kind of tensor math running at half speed: FP16 and BF16 multiplies that accumulate in FP32, and TF32, issue at half the rate of the professional cards built on the same silicon. &lt;code&gt;gpu_unlock&lt;/code&gt;, an open-source kernel module, puts the full rate back at every boot. My 3090 runs headless at home as a local LLM box, mostly serving one 27-billion-parameter coding model through llama.cpp, so the question was what doubling that math buys the work I actually do. I approach every free speedup the same way: I assume the bill is somewhere, and I go looking for it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The proxy said unloaded. The model was loading.</title>
				<link>https://tsvinc.dev/posts/status-said-unloaded/</link>
				<pubDate>Sun, 25 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/status-said-unloaded/</guid>
				<description>&lt;p&gt;Ten times in sixteen seconds the probe asked my proxy for its model list, and ten times it got back the same 54,031 bytes, with the model it had just asked to load listed as &lt;code&gt;unloaded&lt;/code&gt;. After fifteen seconds of that, the probe wrote its verdict and moved on:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;#34;alias&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;3090-flint-40b&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;configured_context&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;131072&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;result&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;3090-flint-40b returned to unloaded during load&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;&amp;#34;total_s&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;18.4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Four of the seven models in that run got the same line. None of them had unloaded. The 3090 box&#39;s router had accepted each load, exactly as asked.&lt;/p&gt;</description>
			</item>
			<item>
				<title>&#34;Terminating immediately&#34; took 90 seconds</title>
				<link>https://tsvinc.dev/posts/terminating-immediately-took-90-seconds/</link>
				<pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/terminating-immediately-took-90-seconds/</guid>
				<description>&lt;p&gt;llama-server keeps a message for the moment you run out of patience with it: &lt;code&gt;Received second interrupt, terminating immediately.&lt;/code&gt; On the 3090 box it printed that at 09:45:04. The next thing systemd had to say about the unit came at 09:46:34, and it was &lt;code&gt;Aborting&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;That stop was half of an engine switch. My LAN proxy for local models stops one llama.cpp build and starts another when a request names a model that only the other build has (&lt;a href=&#34;https://tsvinc.dev/posts/cutting-a-stream-doesnt-cancel-the-turn/&#34;&gt;why it does that&lt;/a&gt;). The proxy logged the new engine up after 1m36s. A switch between those two builds takes 2 to 4 seconds. Two signals did this, the second one came from my own script, and the &amp;quot;immediately&amp;quot; path deadlocked inside glibc.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Cutting a stream doesn&#39;t cancel the turn</title>
				<link>https://tsvinc.dev/posts/cutting-a-stream-doesnt-cancel-the-turn/</link>
				<pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/cutting-a-stream-doesnt-cancel-the-turn/</guid>
				<description>&lt;p&gt;The plan was a router. One OpenAI- and Anthropic-compatible URL on a mini-PC, two GPU boxes behind it, read the request&#39;s &lt;code&gt;model&lt;/code&gt;, pick the box, forward the bytes. I started it at 23:37 one night. By 22:04 the next evening it was starting and stopping llama.cpp builds on the 3090 box (the A9&#39;s benchmarks kept it out that day), deciding when a request has to wait, and shutting engines down after fifteen idle minutes so a benchmark could have the GPU back.&lt;/p&gt;</description>
			</item>
			<item>
				<title>To a coding agent, 503 means try again</title>
				<link>https://tsvinc.dev/posts/503-means-try-again/</link>
				<pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/503-means-try-again/</guid>
				<description>&lt;p&gt;&lt;code&gt;opencode run&lt;/code&gt; printed its banner, &lt;code&gt;&amp;gt; build · mock-err503&lt;/code&gt;, and then nothing. No error, no exit code, no output, until the run was killed. The mock server behind it answered every request with a 503 in my LAN proxy&#39;s error format: the status the proxy sent at the time for any model it couldn&#39;t serve, whether the GPU box was down, the engine switch had failed or a benchmark owned the GPU for the next few hours. opencode was retrying, and it had no plans to stop.&lt;/p&gt;</description>
			</item>
			<item>
				<title>MTP acceptance is a side effect, not a target</title>
				<link>https://tsvinc.dev/posts/mtp-acceptance-not-a-target/</link>
				<pubDate>Wed, 21 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/mtp-acceptance-not-a-target/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you know what speculative decoding is. &lt;a href=&#34;https://tsvinc.dev/posts/benchmark-ran-without-mtp/&#34;&gt;Part 6&lt;/a&gt; covers how the bench turned on MTP drafting for the Qwen3.8 27B tunes.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;The hard-tier table for Swift-1.5, a Qwen3.8-27B tune, ends in a column that reads 0.83: the share of the MTP head&#39;s draft tokens that the model accepted, averaged over every request the server logged. The server drafts three tokens ahead, and the average request keeps 83 percent of them.&lt;/p&gt;</description>
			</item>
			<item>
				<title>It fits in 16 GB. That was the easy question</title>
				<link>https://tsvinc.dev/posts/kv-cache-in-system-ram/</link>
				<pubDate>Tue, 20 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/kv-cache-in-system-ram/</guid>
				<description>&lt;p&gt;&lt;em&gt;Assumes you&#39;ve run llama.cpp and know what the KV cache is.&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;&amp;quot;Will it fit?&amp;quot; is the question everyone asks about a model and a graphics card, because it has a clean yes-or-no answer. A friend asked it about a 16 GB card: can Qwen3.8-27B, or its Swift-1.5 tune, at IQ4_XS (13.3 and 14.4 GiB of weights) run fully on the GPU if the KV cache goes to system RAM? He sent the flags he&#39;d run it with, &lt;code&gt;-t 8 -ctk q8_0 -ctv q8_0&lt;/code&gt;, and the question was what adding &lt;code&gt;-nkvo&lt;/code&gt; does.&lt;/p&gt;</description>
			</item>
			<item>
				<title>My benchmark served the model at half speed</title>
				<link>https://tsvinc.dev/posts/benchmark-ran-without-mtp/</link>
				<pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/benchmark-ran-without-mtp/</guid>
				<description>&lt;p&gt;Nine short agent tasks, one model, an RTX 3090. llama.cpp finished them in 1,521 seconds. open-jet, a megakernel engine, finished them in 629. That is 2.4 times faster, the kind of ratio that gets a post written about a new engine.&lt;/p&gt;&#xA;&lt;p&gt;The engine, on a different quant and drafting one token deeper, accounts for 1.29x of it. The rest came from a flag one of my scripts had and the other didn&#39;t.&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
