Disclosure: Youyeetoo supplied the X1S and NVMe. Testing and conclusions are my own.
My first X1S article answered the bigger question: could this little N5095 board become a dependable Kali-on-NVMe cyberdeck core? Once I had it stable, one question kept bothering me. Was Ollama already getting the most out of the board, or was I leaving useful performance on the table by not building llama.cpp myself and using the Intel GPU?
That matters on a compact board. I wanted to know what would actually improve the experience of using local models on the X1S. What I learned was narrower than the question I started with. The CPU runs used different test harnesses, so they do not settle whether Ollama or llama.cpp is faster. Vulkan did give the two smallest models a clean boost, while the larger runs exposed i915 instability that belongs in the result.
The test I actually ran
The board is the Youyeetoo X1S with an Intel Celeron N5095, 16 GB RAM, the supplied heatsink and active fan, and Kali Linux on NVMe. Five comparisons used the exact Q4_K_M GGUF files behind the original Ollama tags. Gemma needed a derived text-only compatibility copy before current llama.cpp would load it. The saved report identifies llama.cpp commit 9a286ac with an SSE4.2 CPU baseline and Vulkan enabled. The original CMake command and cache were not retained, so this package cannot independently rule out build configuration as another variable.
llama-bench pp128/tg96 workload. Ollama's 96-token setting was only a ceiling. The 0.6B, 1.7B, and 8B responses stopped at 54, 56, and 84 tokens. The main llama.cpp matrix also did not explicitly set the same 4,096-token context. I am publishing each number as it was recorded, not treating the table as a head-to-head winner test. Gemma is separate again because llama.cpp needed the derived text-only copy.Temperature was recorded every two seconds. The 85 °C guard stayed in place. I did not alter a GPU timeout, watchdog, kernel safety control, or firmware setting to obtain a result. The source repository retains the scripts, aggregated summaries, model-blob digests, and the kernel evidence for the GPU failure.
What the CPU measurements do and do not show
| Model | Ollama API warm generation | llama-bench CPU | llama-bench Vulkan |
|---|---|---|---|
| Qwen3 0.6B | 7.81 tok/s | 7.42 tok/s | 8.56 tok/s |
| Qwen3 1.7B | 3.47 tok/s | 2.98 tok/s | 3.48 tok/s |
| Qwen3 4B Instruct | 1.98 tok/s | 1.58 tok/s | 1.46 tok/s, reset timeout |
| Phi-4 Mini | 2.10 tok/s | 1.64 tok/s | 1.48 tok/s, GPU hang logged |
| Gemma 3 4B | 2.12 tok/s | 1.64 tok/s, patched text-only copy | GPU hang |
| Qwen3 8B | 0.98 tok/s | 10-minute cap | 0.84 tok/s, GPU hang logged |
The Ollama API numbers came out higher than the llama-bench CPU numbers in the first four rows. I initially treated that as a runtime win. I should not have. The prompt, harness, and explicitly recorded context did not match, so the difference could come from the test setup rather than the runtime. A fair comparison needs the exact same rendered prompt through Ollama and llama-cli, with the context and every other material setting written down. Until I run that, these are separate measurements from this X1S, not proof that either program is faster.
The clean Vulkan results are Qwen3 0.6B and 1.7B. Within llama-bench, Vulkan lifted generation from 7.42 to 8.56 tok/s and from 2.98 to 3.48 tok/s. The 4B and 8B processes produced numbers, but the kernel logged reset trouble during their run windows. I am retaining those values as diagnostic observations, not treating them as clean performance measurements. Qwen3 8B returned normally at 0.84 tok/s after its CPU test hit the ten-minute cap, but its GPU hang means that return code is not enough to call the run successful.
Vulkan changed prompt processing and thermals
| Clean Vulkan run | Vulkan prompt processing | Vulkan package peak | CPU package peak |
|---|---|---|---|
| Qwen3 0.6B | 37.29 tok/s | 53 °C | 80 °C |
| Qwen3 1.7B | 12.86 tok/s | 56 °C | 82 °C |
In those two clean pairs, Vulkan prompt processing ran at 3.3 to 3.5 times the CPU rate, and the recorded package peaks were 26 to 27 °C lower. That is useful when there is real prompt ingestion to do, such as a long instruction, pasted notes, or a chunk of local documentation. It does not make the N5095 iGPU a reliable accelerator for every model size.
The first Vulkan problem turned out to be a good old Linux permissions problem, not a missing driver. The benchmark account belonged to video but not render, so it could not open /dev/dri/renderD128. Adding the existing render group let Mesa ANV see the GPU. I did not weaken a timeout or safety mechanism to get there.
The larger Vulkan runs crossed the safety boundary
The original runner checked process return codes and temperature, but it collected the kernel summary only after the Vulkan matrix. That was not enough. Qwen3 4B reached a reset timeout near the end of its run, while Phi-4 Mini and Qwen3 8B coincided with explicit i915 GPU hangs. All three processes still returned zero. A normal exit from llama-bench therefore did not prove a clean GPU run. The corrected repository maps each kernel event to its telemetry window and marks those rows as unstable.
I stopped further Vulkan and split-offload testing once I reconstructed that timeline. A safer runner has to watch the kernel during each individual run and stop immediately on an i915 reset or hang, not wait until the entire matrix is over.
Gemma 3 made the failure explicit
Gemma 3 gave me a different problem before I even reached Vulkan. The model file Ollama was using came from an older multimodal conversion that current llama.cpp rejected. I made a separate text-only copy by adding the missing metadata, padding the vocabulary row, and removing the embedded vision tensors. That copy produced the 1.64 tok/s CPU result above. The original file stayed untouched, and the patch script is in the repository so anyone can inspect exactly what changed.
The later Vulkan run was a different failure. It hit fence timeouts, an i915 preemption reset, and vk::DeviceLostError. i915 recovered the GPU and the system remained up. This was the clearest user-space failure, but the reconstructed kernel timeline shows it was not the only unstable Vulkan run. I did not retry by relaxing guard behavior or pretending the error was only a conversion issue. The evidence remains in the repository because the failure mode is part of the benchmark result.
Three more models I wanted to try
| Ollama tag | Generation | Peak package |
|---|---|---|
| granite4:tiny-h | 5.43 tok/s | 79 °C |
| lfm2.5:latest | 4.95 tok/s | 80 °C |
| gemma3n:e2b | 3.24 tok/s | 80 °C |
I ran these through the same original Ollama request because I wanted a few more practical choices than the first six models gave me. All three landed above the original 4B-class range in this pass. That tells me they are worth spending more time with on the X1S. It does not tell me which one writes better answers, follows instructions better, or belongs in every project. Those are different tests.
Qwen3.5 and Gemma 4 on the Celeron N5095
Commenters specifically asked about Qwen3.5 0.8B and 2B, and about Gemma 4 E2B and E4B rather than Gemma 3n. I finished all four after auditing the first result package. They use official Ollama tags, the same 4,096-token context, 96-token generation cap, temperature 0, seed 42, and three-request cold-plus-warm method as the original Ollama rerun.
| Official Ollama tag | Cold generation | Warm average | Recorded package peak |
|---|---|---|---|
| qwen3.5:0.8b, Q8_0 | 10.43 tok/s | 10.44 tok/s | 70 °C |
| qwen3.5:2b, Q8_0 | 4.97 tok/s | 4.89 tok/s | 75 °C |
| gemma4:e2b, Q4_K_M | 3.36 tok/s | 3.38 tok/s | 77 °C |
| gemma4:e4b, Q4_K_M | 1.78 tok/s | 1.78 tok/s | 78 °C |
The 0.8B model is the fastest text-generation result I recorded on the X1S in this work. The 2B model lands just under LFM2.5 and Granite 4 Tiny-H in raw generation speed. Gemma 4 E2B averaged 3.38 tok/s and stopped naturally after 66 generated tokens in each request. E4B averaged 1.78 tok/s and stopped naturally after 82. That is only a throughput comparison. I did not run a task-quality evaluation, and the Q8_0 Qwen weights are not a quantization-matched comparison with every older tag. The raw per-run timings, output hashes, model-blob digests, and temperature peaks are in the repository.
BitCPM 1B exposed a runtime compatibility gap
I also tried OpenBMB's official Apache-2.0 BitCPM-CANN 1B TQ2_0 GGUF. Ollama 0.32.1 downloaded and verified the 550 MB file, then rejected it before inference with tensor "blk.0.attn_k.weight" size overflow. The same file loaded in my pinned llama.cpp build and completed the CPU microbenchmark with zero GPU layers.
| BitCPM-CANN 1B TQ2_0 | Prompt processing | Generation | Recorded package peak |
|---|---|---|---|
| llama.cpp CPU, 2 repetitions | 13.30 tok/s | 8.63 tok/s | 68 °C |
| Ollama 0.32.1 | Model-load failure | Not run | Not applicable |
llama.cpp reported 1.62 billion parameters and identified the file as TQ2_0 at 2.06 bits per weight. This result uses the 128-token prompt and 96-token generation microbenchmark, not the natural-language Ollama request above. It answers a runtime-support question and gives a llama.cpp throughput number, but it is not a new Ollama-versus-llama.cpp head-to-head row.
What this means when I use the X1S
The X1S still makes sense to me as a compact native-x86 Kali and local-AI utility board, as documented in the original build article. I am keeping Ollama for ordinary use because it is already installed and gives me the simplest workflow, not because this round proved it faster. Vulkan was useful and clean with Qwen3 0.6B and 1.7B, but I would not use the larger Vulkan results as performance claims on this software stack. The kernel evidence matters more than a zero process return code.
I have not yet run a matched N100, Raspberry Pi, or Nova shootout. Those need the same artifacts, prompts, runtime settings, cooling disclosure, and guard behavior before they can support a board-to-board claim. The X1S data here is deliberately narrower than that.
X1S runtime benchmark FAQ
Did Vulkan make the X1S faster for local LLMs?
For Qwen3 0.6B and 1.7B, yes. Those two Vulkan runs were clean, prompt processing was much faster, and package temperatures were lower. The 4B and 8B runs were not clean enough for a performance claim because the kernel logged reset timeouts or GPU hangs.
Did Ollama beat llama.cpp on the X1S?
This round cannot support a runtime winner. Five rows reused the same Q4_K_M files, but Ollama ran a natural-language API request at 4,096-token context while llama.cpp ran a synthetic llama-bench pp128/tg96 workload. Ollama used a 96-token ceiling and some responses stopped at 54, 56, or 84 tokens. The main llama.cpp matrix also did not explicitly set the same 4,096-token context. The recorded values remain useful as separate observations, but a fair winner claim needs a same-prompt rerun with every material setting matched.
What failed during the Vulkan tests?
Qwen3 4B reached a kernel reset timeout, and Phi-4 Mini and Qwen3 8B coincided with i915 GPU hangs even though llama-bench returned normally. Gemma 3 4B later failed explicitly with fence timeouts, an i915 preemption reset, and vk::DeviceLostError. The kernel recovered the GPU each time, but only the 0.6B and 1.7B Vulkan rows are treated as clean measurements.
How fast are Qwen3.5 0.8B and 2B on the Celeron N5095?
Using official Ollama Q8_0 tags, the two warm Qwen3.5 0.8B runs averaged 10.44 tokens per second and the two warm Qwen3.5 2B runs averaged 4.89 tokens per second. Their recorded package peaks were 70 and 75 C.
Were Gemma 4 E2B and E4B tested, or only Gemma 3n E2B?
Both official Gemma 4 variants are now separate measured results. The Q4_K_M E2B tag averaged 3.38 warm tokens per second with a 77 C package peak, while E4B averaged 1.78 with a 78 C peak. The earlier gemma3n:e2b result was 3.24 tokens per second and must not be labeled as Gemma 4.
Does BitCPM-CANN 1B TQ2_0 run on the X1S?
The official GGUF ran in llama.cpp CPU mode at 13.30 prompt tokens per second and 8.63 generation tokens per second, with zero GPU layers and a 68 C package peak. Ollama 0.32.1 rejected the same verified file during model loading with a tensor size overflow.
Get notified when I publish new hardware reviews, benchmarks, and security research. No spam, unsubscribe anytime.
I respect your privacy. Powered by Buttondown.