# Llama.cpp on Apple Silicon -- native build much faster than nixpkgs

**URL:** https://discourse.nixos.org/t/llama-cpp-on-apple-silicon-native-build-much-faster-than-nixpkgs/75309
**Category:** Help
**Created:** [February 14, 2026, 5:27pm UTC](https://discourse.nixos.org/t/llama-cpp-on-apple-silicon-native-build-much-faster-than-nixpkgs/75309 "2026-02-14T17:27:06Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![n8henrie](https://discourse.nixos.org/user_avatar/discourse.nixos.org/n8henrie/32/2452_2.png) [@n8henrie](https://discourse.nixos.org/u/n8henrie)
#### Post date: [February 14, 2026, 5:27pm UTC](https://discourse.nixos.org/t/llama-cpp-on-apple-silicon-native-build-much-faster-than-nixpkgs/75309/1 "2026-02-14T17:27:06Z")

</div>

Hi all,

I finally decided to start experimenting with llama.cpp. On my M4 MBP (64G), I’m seeing significantly faster tokens / sec building from source vs using the packaged version in spite of using metal and blas for both. Why might that be?

Source build using this:

```bash
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash --pure
#!nix-shell -p cmake
#!nix-shell -p git
#!nix-shell -p llvmPackages.openmp
#!nix-shell -p openssl

set -Eeuf -o pipefail
set -x

main() {
  rm -rf ./build
  cmake -B build
  cmake --build build --config Release -j "$(nproc)"
}
main "$@"

```

Benchmark results (intentionally kept out of codeblocks so the md table renders):

```console
$ build/bin/llama-bench \
    -o md \
    -m ~/Library/Caches/llama.cpp/Qwen_Qwen3-Coder-Next-GGUF_Qwen3-Coder-Next-Q4_K_M_Qwen3-Coder-Next-Q4_K_M-00001-of-00004.gguf

```

ggml\_metal\_device\_init: tensor API disabled for pre-M5 and pre-A19 devices  
ggml\_metal\_library\_init: using embedded metal library  
ggml\_metal\_library\_init: loaded in 0.007 sec  
ggml\_metal\_rsets\_init: creating a residency set collection (keep\_alive = 180 s)  
ggml\_metal\_device\_init: GPU name: MTL0  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyApple9 (1009)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyCommon3 (3003)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyMetal4 (5002)  
ggml\_metal\_device\_init: simdgroup reduction = true  
ggml\_metal\_device\_init: simdgroup matrix mul. = true  
ggml\_metal\_device\_init: has unified memory = true  
ggml\_metal\_device\_init: has bfloat = true  
ggml\_metal\_device\_init: has tensor = false  
ggml\_metal\_device\_init: use residency sets = true  
ggml\_metal\_device\_init: use shared buffers = true  
ggml\_metal\_device\_init: recommendedMaxWorkingSetSize = 55662.79 MB

| model | size | params | backend | threads | test | t/s |
| --- | --- | --- | --- | --- | --- | --- |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | pp512 | 803.48 ± 8.01 |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | tg128 | 45.88 ± 0.52 |

build: 01d8eaa28 (8054)

Using nixpkgs version instead:

```console
$ nix-shell \
    -I nixpkgs=flake:github:nixos/nixpkgs \
    -p 'llama-cpp.override { blasSupport = true; }' \
    --run \
    'llama-bench -o md -m ~/Library/Caches/llama.cpp/Qwen_Qwen3-Coder-Next-GGUF_Qwen3-Coder-Next-Q4_K_M_Qwen3-Coder-Next-Q4_K_M-00001-of-00004.gguf'

```

unpacking ‘github:nixos/nixpkgs/a5b1db765309855b657b52ac29170e7898c9c96a’ into the Git cache…  
ggml\_metal\_device\_init: tensor API disabled for pre-M5 and pre-A19 devices  
ggml\_metal\_library\_init: using embedded metal library  
ggml\_metal\_library\_init: loaded in 0.005 sec  
ggml\_metal\_rsets\_init: creating a residency set collection (keep\_alive = 180 s)  
ggml\_metal\_device\_init: GPU name: MTL0  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyApple9 (1009)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyCommon3 (3003)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyMetal4 (5002)  
ggml\_metal\_device\_init: simdgroup reduction = true  
ggml\_metal\_device\_init: simdgroup matrix mul. = true  
ggml\_metal\_device\_init: has unified memory = true  
ggml\_metal\_device\_init: has bfloat = true  
ggml\_metal\_device\_init: has tensor = false  
ggml\_metal\_device\_init: use residency sets = true  
ggml\_metal\_device\_init: use shared buffers = true  
ggml\_metal\_device\_init: recommendedMaxWorkingSetSize = 55662.79 MB

| model | size | params | backend | threads | test | t/s |
| --- | --- | --- | --- | --- | --- | --- |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | pp512 | 622.26 ± 28.07 |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | tg128 | 41.60 ± 0.07 |

build: 8872ad2 (7966)

I’ve repeated a few times and it seems consistent. ~800 vs ~600 is a pretty substantial difference. Are there build flags we could use to improve the version in nixpkgs?

---

<div class="post-metadata">

### Author: ![debtquity](https://discourse.nixos.org/letter_avatar_proxy/v4/letter/d/91b2a8/32.png) [@debtquity](https://discourse.nixos.org/u/debtquity)
#### Post date: [February 14, 2026, 6:28pm UTC](https://discourse.nixos.org/t/llama-cpp-on-apple-silicon-native-build-much-faster-than-nixpkgs/75309/2 "2026-02-14T18:28:26Z")

</div>

hi @n8henrie - I suspect the performance discrepancy has something to do with the different build versions used to run the models. Maybe there were performance improvements between 7966 and 8054? Although, looking at the release history, seems this is updated on a frequent basis as 7966 is only a week old.

source:

> …  
> build: 01d8eaa28 (8054)

nixpkgs:

> …  
> build: 8872ad2 (7966)

In order to rule this out, please build from source using the same version as nixpkgs.

- [Release b7966 · ggml-org/llama.cpp · GitHub](https://github.com/ggml-org/llama.cpp/releases/tag/b7966) (release for `b7966`)
- [https://github.com/ggml-org/llama.cpp/archive/refs/tags/b7966.tar.gz](https://github.com/ggml-org/llama.cpp/archive/refs/tags/b7966.tar.gz) (source code archive)

I would try it myself but I do not have time to download a 46G model.

---

<div class="post-metadata">

### Author: ![n8henrie](https://discourse.nixos.org/user_avatar/discourse.nixos.org/n8henrie/32/2452_2.png) [@n8henrie](https://discourse.nixos.org/u/n8henrie)
#### Post date: [February 14, 2026, 6:45pm UTC](https://discourse.nixos.org/t/llama-cpp-on-apple-silicon-native-build-much-faster-than-nixpkgs/75309/3 "2026-02-14T18:45:13Z")

</div>

Sure enough, this build number matches and so does its benchmark. Thanks!

```console
$ git describe --tag
b7966
$ git rev-parse HEAD
8872ad2125336d209a9911a82101f80095a9831d
$ ./build.sh
$ # ...
$ build/bin/llama-bench \
    -o md \
    -m ~/Library/Caches/llama.cpp/Qwen_Qwen3-Coder-Next-GGUF_Qwen3-Coder-Next-Q4_K_M_Qwen3-Coder-Next-Q4_K_M-00001-of-00004.gguf

```

ggml\_metal\_device\_init: tensor API disabled for pre-M5 and pre-A19 devices  
ggml\_metal\_library\_init: using embedded metal library  
ggml\_metal\_library\_init: loaded in 5.628 sec  
ggml\_metal\_rsets\_init: creating a residency set collection (keep\_alive = 180 s)  
ggml\_metal\_device\_init: GPU name: MTL0  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyApple9 (1009)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyCommon3 (3003)  
ggml\_metal\_device\_init: GPU family: MTLGPUFamilyMetal4 (5002)  
ggml\_metal\_device\_init: simdgroup reduction = true  
ggml\_metal\_device\_init: simdgroup matrix mul. = true  
ggml\_metal\_device\_init: has unified memory = true  
ggml\_metal\_device\_init: has bfloat = true  
ggml\_metal\_device\_init: has tensor = false  
ggml\_metal\_device\_init: use residency sets = true  
ggml\_metal\_device\_init: use shared buffers = true  
ggml\_metal\_device\_init: recommendedMaxWorkingSetSize = 55662.79 MB

| model | size | params | backend | threads | test | t/s |
| --- | --- | --- | --- | --- | --- | --- |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | pp512 | 635.70 ± 13.68 |
| qwen3next 80B.A3B Q4\_K - Medium | 45.08 GiB | 79.67 B | MTL,BLAS | 12 | tg128 | 41.90 ± 0.96 |

build: 8872ad212 (7966)
