llamaperf

Phi-4

Microsoft · 6 reports

Run Phi-4 yourself? Add your numbers.

Your coding agent can run a speed test on your machine and send it here with a free account. Or paste a result you've already posted.

Reported performance for Phi-4

Filter this model’s reports by setup →
Apple hardware
generation:
56.8 tokens/s
prompt processing (prefill):
1537.5 tokens/s
quant:
Q4_K_M (GGUF)
flash attention:
on

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, saved 2026-09-27T00:40:39Z; recovered 2026-10-13. No local model run or reproduction performed. Primary raw result: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf/phi-4-reasoning_Q4_K_M_ngl99.json . Source publication commit is 34fee99b6df6129fb3c64255c1bfb179a54ca044. The author's upstream submission, including corrections and limitations, is https://github.com/enescingoz/mac-llm-bench/pull/12 . Hardware: one Apple Mac Studio Mac17,14, M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified memory; macOS 27.0 build 26A428, bare metal, AC power, High Power energy mode. Source corrects its JSON core labels: the 6/12 split denotes 6 Super and 12 Performance cores, not 12 Efficiency cores. iogpu.wired_limit_mb=32768 is a session limit, not installed RAM or dedicated VRAM. PR reports ambient about 20.6 C, external WD_BLACK SN7100 NVMe in OWC Express 1M2 over USB4, idle Ollama with no model loaded and no other heavy apps. Swap was at most 2 MB when checked every 60 s. No macOS thermal/performance warnings were recorded, but per-model thermal state was not captured. Do not import zero-swap/per-cell thermal claims from the author's separate bandwidth harness. Exact model: bartowski/microsoft_Phi-4-reasoning-plus-GGUF, file microsoft_Phi-4-reasoning-plus-Q4_K_M.gguf, GGUF Q4_K_M. Manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf-revisions.tsv . It records measured repository revision 96b602db19694b8323c8638ad771289fb5be0863 and SHA256 fcb2cdd14881e20613f56d37f49d0c73ec6c00f9bb4d0e4b161a1621d8517f47. The exact revision's HF file page was independently read and its displayed SHA256 matched: https://huggingface.co/bartowski/microsoft_Phi-4-reasoning-plus-GGUF/blob/96b602db19694b8323c8638ad771289fb5be0863/microsoft_Phi-4-reasoning-plus-Q4_K_M.gguf . This binds model identity and quantized artifact; today's main is not substituted for the measured revision. Source nominal model size label is 14B. Runtime: llama.cpp Homebrew build 11146, commit 7fe450e19, ggml 0.25.3, Metal. The raw runtime.version accidentally stores a load_backend BLAS log line; the author explicitly corrects it in PR 12 and reports Metal 4 tensor API active. This is not a CPU-only BLAS benchmark. Each model was run in a separate ./bench_gguf.sh --model process because --auto stopped after the first model. Source parameters are n_gpu_layers=99, flash_attention=true, threads=0. The helper omits -t when threads=0; this means runtime default rather than zero running threads. Requested 99 GPU layers is not a measured layer-offload count. Quantization above describes weights, not KV cache. Headline generation is tg128=56.84 tokens/s; prompt processing is pp512=1537.47 tokens/s. These are separate native llama-bench microtests from the same campaign, not one 512-input/128-output request, an average across lengths, or server concurrency throughput. All retained native rates in tokens/s: pp128=1067.98; pp256=1447.19; pp512=1537.47; tg128=56.84; tg256=56.74. The pp tests process 128/256/512 synthetic token IDs; the tg tests perform 128/256 one-token decode steps without a preceding 512-token prompt. The context field is intentionally unspecified: these test lengths are not an advertised context window or a long-context setting. Metric method: published mac-llm-bench bench_gguf.sh entrypoint passes -p 128,256,512 -n 128,256 -ngl 99 -fa 1 to llama-bench. It first runs human-readable output, then a separate -o json invocation for saved speed results; those two invocations are not combined. This entrypoint has inline speed/memory logic; the separate lib/run_bench_gguf.sh helper is not the saved-speed entrypoint, so its different display/capture ordering must not be substituted. lib/collect_results.sh maps native n_prompt/n_gen and avg_ts into these speed keys and rounds to 2 decimals. Native llama.cpp code at the reported 7fe450e19 revision times synchronized inference, computes each repetition's token count divided by elapsed nanoseconds, then takes the arithmetic mean of those rates. This is not input divided by TTFT, total wall time, or a pooled count/total-duration calculation. The pinned llama-bench defaults are 5 repetitions, warmup enabled, depth 0, with model memory cleared before each timed repetition; PP uses synthetic random IDs and TG sequential random IDs, without sampling meaningful chat output. This establishes native benchmark semantics. The exact executed shell-harness commit and full raw llama-bench samples, durations, dispersion and command log were not preserved in this result, so the 5-repetition/default-cache interpretation is code/protocol-derived rather than independently counted from raw samples. Current upstream shell code is supporting method evidence, not proof of byte-for-byte historical reproduction. KV precision, actual CPU thread count, realized batch settings, speculation/MTP and quality scores are not separately captured in this JSON; no quality validation or conversational thinking-mode conclusion follows. Memory: file_size_gb=8.43 is the on-disk file size divided by 2^30, despite the GB key. Source peak_rss_gb=8.59 is separately measured process maximum RSS. The published entrypoint obtains RSS with /usr/bin/time -l on a separate llama-bench -p 32 -n 1 invocation, then divides bytes by 2^30. It is not the timed speed test's peak, dedicated VRAM, model-only allocation or installed capacity. The per-record available_ram_gb=18.7 is available system memory at collection, not model usage. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/bench_gguf.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ggml-org/llama.cpp/blob/7fe450e19/tools/llama-bench/llama-bench.cpp . Source data/documentation license is CC BY 4.0. All values remain source-reported single-machine results; these short synthetic tests do not establish long-context, multi-user or application end-to-end performance.

Oct 13, 2026
Apple hardware
generation:
164.9 tokens/s
prompt processing (prefill):
5412.7 tokens/s
quant:
Q4_K_M (GGUF)
flash attention:
on

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, saved 2026-09-27T00:36:26Z; recovered 2026-10-13. No local model run or reproduction performed. Primary raw result: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf/phi-4-mini-reasoning_Q4_K_M_ngl99.json . Source publication commit is 34fee99b6df6129fb3c64255c1bfb179a54ca044. The author's upstream submission, including corrections and limitations, is https://github.com/enescingoz/mac-llm-bench/pull/12 . Hardware: one Apple Mac Studio Mac17,14, M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified memory; macOS 27.0 build 26A428, bare metal, AC power, High Power energy mode. Source corrects its JSON core labels: the 6/12 split denotes 6 Super and 12 Performance cores, not 12 Efficiency cores. iogpu.wired_limit_mb=32768 is a session limit, not installed RAM or dedicated VRAM. PR reports ambient about 20.6 C, external WD_BLACK SN7100 NVMe in OWC Express 1M2 over USB4, idle Ollama with no model loaded and no other heavy apps. Swap was at most 2 MB when checked every 60 s. No macOS thermal/performance warnings were recorded, but per-model thermal state was not captured. Do not import zero-swap/per-cell thermal claims from the author's separate bandwidth harness. Exact model: bartowski/microsoft_Phi-4-mini-reasoning-GGUF, file microsoft_Phi-4-mini-reasoning-Q4_K_M.gguf, GGUF Q4_K_M. Manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf-revisions.tsv . It records measured repository revision 519790c46093945c24bed49875702ad9126c721c and SHA256 ce8becd58f350d8ae0ec3bbb201ab36f750ffab17ab6238f39292d12ab68ea06. The exact revision's HF file page was independently read and its displayed SHA256 matched: https://huggingface.co/bartowski/microsoft_Phi-4-mini-reasoning-GGUF/blob/519790c46093945c24bed49875702ad9126c721c/microsoft_Phi-4-mini-reasoning-Q4_K_M.gguf . This binds model identity and quantized artifact; today's main is not substituted for the measured revision. Source nominal model size label is 3.8B. Runtime: llama.cpp Homebrew build 11146, commit 7fe450e19, ggml 0.25.3, Metal. The raw runtime.version accidentally stores a load_backend BLAS log line; the author explicitly corrects it in PR 12 and reports Metal 4 tensor API active. This is not a CPU-only BLAS benchmark. Each model was run in a separate ./bench_gguf.sh --model process because --auto stopped after the first model. Source parameters are n_gpu_layers=99, flash_attention=true, threads=0. The helper omits -t when threads=0; this means runtime default rather than zero running threads. Requested 99 GPU layers is not a measured layer-offload count. Quantization above describes weights, not KV cache. Headline generation is tg128=164.86 tokens/s; prompt processing is pp512=5412.68 tokens/s. These are separate native llama-bench microtests from the same campaign, not one 512-input/128-output request, an average across lengths, or server concurrency throughput. All retained native rates in tokens/s: pp128=3338.96; pp256=4803.38; pp512=5412.68; tg128=164.86; tg256=164.18. The pp tests process 128/256/512 synthetic token IDs; the tg tests perform 128/256 one-token decode steps without a preceding 512-token prompt. The context field is intentionally unspecified: these test lengths are not an advertised context window or a long-context setting. Metric method: published mac-llm-bench bench_gguf.sh entrypoint passes -p 128,256,512 -n 128,256 -ngl 99 -fa 1 to llama-bench. It first runs human-readable output, then a separate -o json invocation for saved speed results; those two invocations are not combined. This entrypoint has inline speed/memory logic; the separate lib/run_bench_gguf.sh helper is not the saved-speed entrypoint, so its different display/capture ordering must not be substituted. lib/collect_results.sh maps native n_prompt/n_gen and avg_ts into these speed keys and rounds to 2 decimals. Native llama.cpp code at the reported 7fe450e19 revision times synchronized inference, computes each repetition's token count divided by elapsed nanoseconds, then takes the arithmetic mean of those rates. This is not input divided by TTFT, total wall time, or a pooled count/total-duration calculation. The pinned llama-bench defaults are 5 repetitions, warmup enabled, depth 0, with model memory cleared before each timed repetition; PP uses synthetic random IDs and TG sequential random IDs, without sampling meaningful chat output. This establishes native benchmark semantics. The exact executed shell-harness commit and full raw llama-bench samples, durations, dispersion and command log were not preserved in this result, so the 5-repetition/default-cache interpretation is code/protocol-derived rather than independently counted from raw samples. Current upstream shell code is supporting method evidence, not proof of byte-for-byte historical reproduction. KV precision, actual CPU thread count, realized batch settings, speculation/MTP and quality scores are not separately captured in this JSON; no quality validation or conversational thinking-mode conclusion follows. Memory: file_size_gb=2.32 is the on-disk file size divided by 2^30, despite the GB key. Source peak_rss_gb=2.48 is separately measured process maximum RSS. The published entrypoint obtains RSS with /usr/bin/time -l on a separate llama-bench -p 32 -n 1 invocation, then divides bytes by 2^30. It is not the timed speed test's peak, dedicated VRAM, model-only allocation or installed capacity. The per-record available_ram_gb=21.2 is available system memory at collection, not model usage. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/bench_gguf.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ggml-org/llama.cpp/blob/7fe450e19/tools/llama-bench/llama-bench.cpp . Source data/documentation license is CC BY 4.0. All values remain source-reported single-machine results; these short synthetic tests do not establish long-context, multi-user or application end-to-end performance.

Oct 13, 2026
Apple hardware
generation:
165.0 tokens/s
prompt processing (prefill):
5416.2 tokens/s
quant:
Q4_K_M (GGUF)
flash attention:
on

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, saved 2026-09-27T00:31:32Z; recovered 2026-10-13. No local model run or reproduction performed. Primary raw result: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf/phi-4-mini_Q4_K_M_ngl99.json . Source publication commit is 34fee99b6df6129fb3c64255c1bfb179a54ca044. The author's upstream submission, including corrections and limitations, is https://github.com/enescingoz/mac-llm-bench/pull/12 . Hardware: one Apple Mac Studio Mac17,14, M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified memory; macOS 27.0 build 26A428, bare metal, AC power, High Power energy mode. Source corrects its JSON core labels: the 6/12 split denotes 6 Super and 12 Performance cores, not 12 Efficiency cores. iogpu.wired_limit_mb=32768 is a session limit, not installed RAM or dedicated VRAM. PR reports ambient about 20.6 C, external WD_BLACK SN7100 NVMe in OWC Express 1M2 over USB4, idle Ollama with no model loaded and no other heavy apps. Swap was at most 2 MB when checked every 60 s. No macOS thermal/performance warnings were recorded, but per-model thermal state was not captured. Do not import zero-swap/per-cell thermal claims from the author's separate bandwidth harness. Exact model: bartowski/microsoft_Phi-4-mini-instruct-GGUF, file microsoft_Phi-4-mini-instruct-Q4_K_M.gguf, GGUF Q4_K_M. Manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf-revisions.tsv . It records measured repository revision 7ff82c2aaa4dde30121698a973765f39be5288c0 and SHA256 01999f17c39cc3074afae5e9c539bc82d45f2dd7faa3917c66cbef76fce8c0c2. The exact revision's HF file page was independently read and its displayed SHA256 matched: https://huggingface.co/bartowski/microsoft_Phi-4-mini-instruct-GGUF/blob/7ff82c2aaa4dde30121698a973765f39be5288c0/microsoft_Phi-4-mini-instruct-Q4_K_M.gguf . This binds model identity and quantized artifact; today's main is not substituted for the measured revision. Source nominal model size label is 3.8B. Runtime: llama.cpp Homebrew build 11146, commit 7fe450e19, ggml 0.25.3, Metal. The raw runtime.version accidentally stores a load_backend BLAS log line; the author explicitly corrects it in PR 12 and reports Metal 4 tensor API active. This is not a CPU-only BLAS benchmark. Each model was run in a separate ./bench_gguf.sh --model process because --auto stopped after the first model. Source parameters are n_gpu_layers=99, flash_attention=true, threads=0. The helper omits -t when threads=0; this means runtime default rather than zero running threads. Requested 99 GPU layers is not a measured layer-offload count. Quantization above describes weights, not KV cache. Headline generation is tg128=164.99 tokens/s; prompt processing is pp512=5416.24 tokens/s. These are separate native llama-bench microtests from the same campaign, not one 512-input/128-output request, an average across lengths, or server concurrency throughput. All retained native rates in tokens/s: pp128=3372.73; pp256=4807.5; pp512=5416.24; tg128=164.99; tg256=164.68. The pp tests process 128/256/512 synthetic token IDs; the tg tests perform 128/256 one-token decode steps without a preceding 512-token prompt. The context field is intentionally unspecified: these test lengths are not an advertised context window or a long-context setting. Metric method: published mac-llm-bench bench_gguf.sh entrypoint passes -p 128,256,512 -n 128,256 -ngl 99 -fa 1 to llama-bench. It first runs human-readable output, then a separate -o json invocation for saved speed results; those two invocations are not combined. This entrypoint has inline speed/memory logic; the separate lib/run_bench_gguf.sh helper is not the saved-speed entrypoint, so its different display/capture ordering must not be substituted. lib/collect_results.sh maps native n_prompt/n_gen and avg_ts into these speed keys and rounds to 2 decimals. Native llama.cpp code at the reported 7fe450e19 revision times synchronized inference, computes each repetition's token count divided by elapsed nanoseconds, then takes the arithmetic mean of those rates. This is not input divided by TTFT, total wall time, or a pooled count/total-duration calculation. The pinned llama-bench defaults are 5 repetitions, warmup enabled, depth 0, with model memory cleared before each timed repetition; PP uses synthetic random IDs and TG sequential random IDs, without sampling meaningful chat output. This establishes native benchmark semantics. The exact executed shell-harness commit and full raw llama-bench samples, durations, dispersion and command log were not preserved in this result, so the 5-repetition/default-cache interpretation is code/protocol-derived rather than independently counted from raw samples. Current upstream shell code is supporting method evidence, not proof of byte-for-byte historical reproduction. KV precision, actual CPU thread count, realized batch settings, speculation/MTP and quality scores are not separately captured in this JSON; no quality validation or conversational thinking-mode conclusion follows. Memory: file_size_gb=2.32 is the on-disk file size divided by 2^30, despite the GB key. Source peak_rss_gb=2.48 is separately measured process maximum RSS. The published entrypoint obtains RSS with /usr/bin/time -l on a separate llama-bench -p 32 -n 1 invocation, then divides bytes by 2^30. It is not the timed speed test's peak, dedicated VRAM, model-only allocation or installed capacity. The per-record available_ram_gb=21.1 is available system memory at collection, not model usage. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/bench_gguf.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ggml-org/llama.cpp/blob/7fe450e19/tools/llama-bench/llama-bench.cpp . Source data/documentation license is CC BY 4.0. All values remain source-reported single-machine results; these short synthetic tests do not establish long-context, multi-user or application end-to-end performance.

Oct 13, 2026
Apple hardware
generation:
56.3 tokens/s
prompt processing (prefill):
1534.2 tokens/s
quant:
Q4_K_M (GGUF)
flash attention:
on

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, saved 2026-09-27T00:30:14Z; recovered 2026-10-13. No local model run or reproduction performed. Primary raw result: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf/phi-4_Q4_K_M_ngl99.json . Source publication commit is 34fee99b6df6129fb3c64255c1bfb179a54ca044. The author's upstream submission, including corrections and limitations, is https://github.com/enescingoz/mac-llm-bench/pull/12 . Hardware: one Apple Mac Studio Mac17,14, M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified memory; macOS 27.0 build 26A428, bare metal, AC power, High Power energy mode. Source corrects its JSON core labels: the 6/12 split denotes 6 Super and 12 Performance cores, not 12 Efficiency cores. iogpu.wired_limit_mb=32768 is a session limit, not installed RAM or dedicated VRAM. PR reports ambient about 20.6 C, external WD_BLACK SN7100 NVMe in OWC Express 1M2 over USB4, idle Ollama with no model loaded and no other heavy apps. Swap was at most 2 MB when checked every 60 s. No macOS thermal/performance warnings were recorded, but per-model thermal state was not captured. Do not import zero-swap/per-cell thermal claims from the author's separate bandwidth harness. Exact model: bartowski/phi-4-GGUF, file phi-4-Q4_K_M.gguf, GGUF Q4_K_M. Manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/gguf-revisions.tsv . It records measured repository revision 19cd65f97c2f1712a81c506611d3f9c94b16a1e1 and SHA256 009aba717c09d4a35890c7d35eb59d54e1dba884c7c526e7197d9c13ab5911d9. The exact revision's HF file page was independently read and its displayed SHA256 matched: https://huggingface.co/bartowski/phi-4-GGUF/blob/19cd65f97c2f1712a81c506611d3f9c94b16a1e1/phi-4-Q4_K_M.gguf . This binds model identity and quantized artifact; today's main is not substituted for the measured revision. Source nominal model size label is 14B. Runtime: llama.cpp Homebrew build 11146, commit 7fe450e19, ggml 0.25.3, Metal. The raw runtime.version accidentally stores a load_backend BLAS log line; the author explicitly corrects it in PR 12 and reports Metal 4 tensor API active. This is not a CPU-only BLAS benchmark. Each model was run in a separate ./bench_gguf.sh --model process because --auto stopped after the first model. Source parameters are n_gpu_layers=99, flash_attention=true, threads=0. The helper omits -t when threads=0; this means runtime default rather than zero running threads. Requested 99 GPU layers is not a measured layer-offload count. Quantization above describes weights, not KV cache. Headline generation is tg128=56.27 tokens/s; prompt processing is pp512=1534.2 tokens/s. These are separate native llama-bench microtests from the same campaign, not one 512-input/128-output request, an average across lengths, or server concurrency throughput. All retained native rates in tokens/s: pp128=1068.37; pp256=1445.26; pp512=1534.2; tg128=56.27; tg256=56.24. The pp tests process 128/256/512 synthetic token IDs; the tg tests perform 128/256 one-token decode steps without a preceding 512-token prompt. The context field is intentionally unspecified: these test lengths are not an advertised context window or a long-context setting. Metric method: published mac-llm-bench bench_gguf.sh entrypoint passes -p 128,256,512 -n 128,256 -ngl 99 -fa 1 to llama-bench. It first runs human-readable output, then a separate -o json invocation for saved speed results; those two invocations are not combined. This entrypoint has inline speed/memory logic; the separate lib/run_bench_gguf.sh helper is not the saved-speed entrypoint, so its different display/capture ordering must not be substituted. lib/collect_results.sh maps native n_prompt/n_gen and avg_ts into these speed keys and rounds to 2 decimals. Native llama.cpp code at the reported 7fe450e19 revision times synchronized inference, computes each repetition's token count divided by elapsed nanoseconds, then takes the arithmetic mean of those rates. This is not input divided by TTFT, total wall time, or a pooled count/total-duration calculation. The pinned llama-bench defaults are 5 repetitions, warmup enabled, depth 0, with model memory cleared before each timed repetition; PP uses synthetic random IDs and TG sequential random IDs, without sampling meaningful chat output. This establishes native benchmark semantics. The exact executed shell-harness commit and full raw llama-bench samples, durations, dispersion and command log were not preserved in this result, so the 5-repetition/default-cache interpretation is code/protocol-derived rather than independently counted from raw samples. Current upstream shell code is supporting method evidence, not proof of byte-for-byte historical reproduction. KV precision, actual CPU thread count, realized batch settings, speculation/MTP and quality scores are not separately captured in this JSON; no quality validation or conversational thinking-mode conclusion follows. Memory: file_size_gb=8.43 is the on-disk file size divided by 2^30, despite the GB key. Source peak_rss_gb=8.59 is separately measured process maximum RSS. The published entrypoint obtains RSS with /usr/bin/time -l on a separate llama-bench -p 32 -n 1 invocation, then divides bytes by 2^30. It is not the timed speed test's peak, dedicated VRAM, model-only allocation or installed capacity. The per-record available_ram_gb=18.8 is available system memory at collection, not model usage. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/bench_gguf.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ggml-org/llama.cpp/blob/7fe450e19/tools/llama-bench/llama-bench.cpp . Source data/documentation license is CC BY 4.0. All values remain source-reported single-machine results; these short synthetic tests do not establish long-context, multi-user or application end-to-end performance.

Oct 13, 2026
Apple hardware
generation:
190.8 tokens/s
prompt processing (prefill):
6281.4 tokens/s
quant:
4-bit (MLX)

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, measured 2026-09-27T20:14:47Z; recovered 2026-10-13. No new run or local reproduction. Raw source: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/mlx/phi-4-mini-instruct-4bit_4bit_ngl99.json . Companion provenance: https://github.com/enescingoz/mac-llm-bench/pull/12 . The source states these are unedited copies of its upstream submission. Data files show public-release commit 34fee99b6df6129fb3c64255c1bfb179a54ca044 (September 27, 2026); the measurement predates discovery. One report groups this model, precision, runtime and hardware; all retained lengths are below. Hardware: one Mac Studio (source PR identifies Mac17,14), Apple M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified RAM, macOS 27.0 (PR build 26A428), AC power and High Power energy mode. Source CPU JSON labels performance_cores=6 and efficiency_cores=12; author clarifies these are 6 Super plus 12 Performance cores. Reported 614 GB/s is theoretical bandwidth. Installed unified RAM is not dedicated VRAM. The raw available_ram_gb=30.2 is a system-availability snapshot, not installed capacity or model allocation. The source records a 32768 MB iogpu wired limit, swap <=2 MB checked every 60 seconds, no system thermal/performance warning, ambient about 20.6 C, external NVMe model storage, and idle Ollama with no model loaded. Per-model temperature, clock and wall power are unknown. Model: mlx-community/phi-4-mini-instruct-4bit, source quant=4bit, MLX weights in Safetensors. Recorded fetched HF snapshot: ac1c269cb4222a4e136a3d09edad301056c1f36a; manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/mlx-revisions.tsv . Identity verified individually at https://huggingface.co/mlx-community/Phi-4-mini-instruct-4bit . Current card identifies conversion from microsoft/Phi-4-mini-instruct. The snapshot is source-reported; model files were not downloaded or hashed, and current main must not be substituted for the recorded revision. Source spells the repo mlx-community/phi-4-mini-instruct-4bit; the current HF canonical URL uses mlx-community/Phi-4-mini-instruct-4bit. The canonical repository directly exposes the same recorded snapshot, verified at https://huggingface.co/mlx-community/Phi-4-mini-instruct-4bit/tree/ac1c269cb4222a4e136a3d09edad301056c1f36a; lowercase alias/redirect behavior remains unverified. Source file_size_gb=0 is a serializer placeholder for MLX repo strings, not a zero-byte model. Conversion-library versions on HF describe conversion, not the measured runtime. Runtime: source JSON mlx-lm 0.31.3; source PR additionally reports mlx 0.32.2 and Python 3.12. One model invocation per process using ./bench_mlx.sh --repo <repo> --cleanup. The author reports cleanup path bugs; this does not establish a deleted model cache or cold load. Source's generic n_gpu_layers=99, flash_attention=true, threads=0 fields are hard-coded by the MLX serializer and do not verify actual MLX offload layers, Flash Attention setting or thread count. These feature fields stay unknown rather than borrowing llama.cpp flags. Configured context capacity is not recorded; prompt length is not context-window capacity. All retained source speed values, tokens/s: pp128=3728.47; pp256=5040.15; pp512=6281.44; tg128=190.81; tg256=192.31. Headline uses pp512=6281.44 and tg128=190.81, not a best-of sweep or an average across prompt lengths. Linkage is inferred from the published wrapper's overwrite order, not independently retained per-trial logs. The current wrapper runs (prompt,generation)=(128,128),(128,256),(256,128),(256,256),(512,128), skipping (512,256); it overwrites each pp and tg key on every success. Therefore if all documented calls completed, the retained pp128 is from (128,256), pp256 and tg256 from (256,256), and pp512 and tg128 from (512,128). The exported dictionary loses the other paired rates, trial-level variance and failure details; do not reconstruct them. The historical executable/harness commit is unpinned. The source claims documented commands without deviations; current upstream code establishes method and interpretation, not byte-for-byte historical reproduction. Timing method: mlx-lm v0.31.3 benchmark.py uses seeded random token IDs, batch size 1 by default, disables EOS stopping, performs one warmup then defaults to five measured trials for each configuration, and prints arithmetic means of native response rates. The wrapper defaults to five trials, parses those means and rounds speed to two decimals. The benchmark is synthetic text-token throughput, not conversational quality or end-to-end request throughput. Published versioned stream_generate measures prompt.size divided by elapsed time to its first generated token, then resets the timer and reports (n+1)/elapsed for generation. Thus PP is a native engine phase rate with first-token work included; it is not input tokens divided by client/network TTFT, load time or total request wall time. TG follows the library's own numerator/timer convention, not a newly recomputed rate. Each generate call makes a new prompt cache when none is supplied, while the model is already loaded and warmed. The source logs do not independently validate cache state; avoid a claim of proven cold prefill. No chat template, --no-think, speculative draft, MTP or quantized KV option is passed by this published benchmark. Default greedy sampler, unquantized KV and prefill step 2048 are code-derived defaults, not separately recorded run flags; corresponding form fields remain unknown. Memory: source memory.peak_rss_gb=2.97. Despite that field name, the MLX exporter passes the highest native peak_memory mean among configurations. v0.31.3 stream_generate uses mx.get_peak_memory()/1e9, an MLX allocator high-water measurement in decimal GB, not operating-system process RSS, installed RAM, dedicated VRAM or necessarily a reset per-trial peak. No RSS/model-size claim is made. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/lib/run_bench_mlx.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/bench_mlx.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ml-explore/mlx-lm/blob/v0.31.3/mlx_lm/benchmark.py ; https://github.com/ml-explore/mlx-lm/blob/v0.31.3/mlx_lm/generate.py . No HumanEval+ or other model-quality score is included for this campaign.

Oct 13, 2026
Apple hardware
generation:
62.1 tokens/s
prompt processing (prefill):
1685.9 tokens/s
quant:
4-bit (MLX)

Reported by the source; GPU count, offloading and concurrent requests can change these figures. Prompt-processing speed is input throughput, not time to first token. Check the full setup before comparing.

Source-reported historical campaign by emihiggins, measured 2026-09-27T20:13:12Z; recovered 2026-10-13. No new run or local reproduction. Raw source: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/mlx/phi-4-4bit_4bit_ngl99.json . Companion provenance: https://github.com/enescingoz/mac-llm-bench/pull/12 . The source states these are unedited copies of its upstream submission. Data files show public-release commit 34fee99b6df6129fb3c64255c1bfb179a54ca044 (September 27, 2026); the measurement predates discovery. One report groups this model, precision, runtime and hardware; all retained lengths are below. Hardware: one Mac Studio (source PR identifies Mac17,14), Apple M5 Max, 18 CPU cores and 40 GPU cores, 48 GB unified RAM, macOS 27.0 (PR build 26A428), AC power and High Power energy mode. Source CPU JSON labels performance_cores=6 and efficiency_cores=12; author clarifies these are 6 Super plus 12 Performance cores. Reported 614 GB/s is theoretical bandwidth. Installed unified RAM is not dedicated VRAM. The raw available_ram_gb=30.1 is a system-availability snapshot, not installed capacity or model allocation. The source records a 32768 MB iogpu wired limit, swap <=2 MB checked every 60 seconds, no system thermal/performance warning, ambient about 20.6 C, external NVMe model storage, and idle Ollama with no model loaded. Per-model temperature, clock and wall power are unknown. Model: mlx-community/phi-4-4bit, source quant=4bit, MLX weights in Safetensors. Recorded fetched HF snapshot: fc0f8f23d369dc29b55cad1d65cb5bf0dcbee910; manifest: https://github.com/emihiggins/m5-max-llm-bench/blob/main/data/mac-llm-bench/m5-max_18c-40g_48gb/mlx-revisions.tsv . Identity verified individually at https://huggingface.co/mlx-community/phi-4-4bit . Current card identifies conversion from microsoft/phi-4. The snapshot is source-reported; model files were not downloaded or hashed, and current main must not be substituted for the recorded revision. Source file_size_gb=0 is a serializer placeholder for MLX repo strings, not a zero-byte model. Conversion-library versions on HF describe conversion, not the measured runtime. Runtime: source JSON mlx-lm 0.31.3; source PR additionally reports mlx 0.32.2 and Python 3.12. One model invocation per process using ./bench_mlx.sh --repo <repo> --cleanup. The author reports cleanup path bugs; this does not establish a deleted model cache or cold load. Source's generic n_gpu_layers=99, flash_attention=true, threads=0 fields are hard-coded by the MLX serializer and do not verify actual MLX offload layers, Flash Attention setting or thread count. These feature fields stay unknown rather than borrowing llama.cpp flags. Configured context capacity is not recorded; prompt length is not context-window capacity. All retained source speed values, tokens/s: pp128=1177.05; pp256=1469.71; pp512=1685.9; tg128=62.05; tg256=62.51. Headline uses pp512=1685.9 and tg128=62.05, not a best-of sweep or an average across prompt lengths. Linkage is inferred from the published wrapper's overwrite order, not independently retained per-trial logs. The current wrapper runs (prompt,generation)=(128,128),(128,256),(256,128),(256,256),(512,128), skipping (512,256); it overwrites each pp and tg key on every success. Therefore if all documented calls completed, the retained pp128 is from (128,256), pp256 and tg256 from (256,256), and pp512 and tg128 from (512,128). The exported dictionary loses the other paired rates, trial-level variance and failure details; do not reconstruct them. The historical executable/harness commit is unpinned. The source claims documented commands without deviations; current upstream code establishes method and interpretation, not byte-for-byte historical reproduction. Timing method: mlx-lm v0.31.3 benchmark.py uses seeded random token IDs, batch size 1 by default, disables EOS stopping, performs one warmup then defaults to five measured trials for each configuration, and prints arithmetic means of native response rates. The wrapper defaults to five trials, parses those means and rounds speed to two decimals. The benchmark is synthetic text-token throughput, not conversational quality or end-to-end request throughput. Published versioned stream_generate measures prompt.size divided by elapsed time to its first generated token, then resets the timer and reports (n+1)/elapsed for generation. Thus PP is a native engine phase rate with first-token work included; it is not input tokens divided by client/network TTFT, load time or total request wall time. TG follows the library's own numerator/timer convention, not a newly recomputed rate. Each generate call makes a new prompt cache when none is supplied, while the model is already loaded and warmed. The source logs do not independently validate cache state; avoid a claim of proven cold prefill. No chat template, --no-think, speculative draft, MTP or quantized KV option is passed by this published benchmark. Default greedy sampler, unquantized KV and prefill step 2048 are code-derived defaults, not separately recorded run flags; corresponding form fields remain unknown. Memory: source memory.peak_rss_gb=8.912. Despite that field name, the MLX exporter passes the highest native peak_memory mean among configurations. v0.31.3 stream_generate uses mx.get_peak_memory()/1e9, an MLX allocator high-water measurement in decimal GB, not operating-system process RSS, installed RAM, dedicated VRAM or necessarily a reset per-trial peak. No RSS/model-size claim is made. Method sources: https://github.com/enescingoz/mac-llm-bench/blob/main/lib/run_bench_mlx.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/bench_mlx.sh ; https://github.com/enescingoz/mac-llm-bench/blob/main/lib/collect_results.sh ; https://github.com/ml-explore/mlx-lm/blob/v0.31.3/mlx_lm/benchmark.py ; https://github.com/ml-explore/mlx-lm/blob/v0.31.3/mlx_lm/generate.py . No HumanEval+ or other model-quality score is included for this campaign.

Oct 13, 2026
Engines people run Phi-4 with
EngineReports
llama.cpp4
MLX2

Get a weekly email of new Phi-4 reports on any GPU.

Email me new reports

Reported configurations

Individual observations from this page, not expected speeds or a ranking. Select a model to open its report, with the source and offloading conditions. Reported context may be a limit rather than actual input length.

Model / hardwareQuant / engineReported contextGeneration
Phi-4 reasoning-plus Q4_K_M; llama-bench TG128 / PP512
M5 Max 48GB
Q4_K_M
llama.cpp
Not reported56.8 tokens/s
Phi-4 mini-reasoning Q4_K_M; llama-bench TG128 / PP512
M5 Max 48GB
Q4_K_M
llama.cpp
Not reported164.9 tokens/s
Phi-4 mini-instruct Q4_K_M; llama-bench TG128 / PP512
M5 Max 48GB
Q4_K_M
llama.cpp
Not reported165.0 tokens/s
Phi-4 Q4_K_M; llama-bench TG128 / PP512
M5 Max 48GB
Q4_K_M
llama.cpp
Not reported56.3 tokens/s
Phi-4 mini-instruct 4-bit; native pp512/tg128 summary
M5 Max 48GB
4-bit
MLX
Not reported190.8 tokens/s
Phi-4 4-bit; native pp512/tg128 summary
M5 Max 48GB
4-bit
MLX
Not reported62.1 tokens/s