FOOTPRINT

Running the cohort on a laptop

CPU only, CUDA_VISIBLE_DEVICES empty, 8 pinned threads. Decoders via GGUF Q4_K_M under llama.cpp, encoders via dynamic int8 under transformers. 14 arms were converted or quantized and 13 have a published rows/min figure.

Memory

Nothing in the cohort reaches 24 GiB, and nothing reaches 8 GiB. The hungriest arm is Phi-4-mini at 3.137 GiB irreducible peak RSS, 5.048 GiB worst-observed under mmap, which leaves 4.863 GiB spare on an 8 GiB machine. Q4_K_M files run 0.871 GiB (OLMo-2-1B) to 2.323 GiB (Phi-4-mini).

The cohort's memory envelope against an 8 GiB and a 24 GiB machine

Nothing in the cohort reaches 8 GiB. The hungriest arm leaves 4.863 GiB spare on an 8 GiB machine.

0 4 8 12 16 20 24 8 GiB 24 GiB Q4_K_M, OLMo-2-1B (smallest) 0.87 Q4_K_M, Phi-4-mini (largest) 2.32 Peak RSS, Phi-4-mini (irreducible) 3.14 Peak RSS, Phi-4-mini (worst observed) 5.05
Table view (every plotted value)
QuantityArmGiB
Q4_K_M file, smallestOLMo-2-1B0.871
Q4_K_M file, largestPhi-4-mini2.323
Peak RSS, irreduciblePhi-4-mini3.137
Peak RSS, worst observed under mmapPhi-4-mini5.048
Peak RSS came from the kernel's VmHWM high-water mark polled every 5 ms and cross-checked against getrusage. It already includes the weights, so it is not additive with the Q4_K_M file size. Every value plotted here is read at build time from pinned/laptop-feasibility.json. The table view lists them all.

Throughput

At 8 threads the fastest arm, OLMo-2-1B, does 30.38 rows/min and the slowest, granite-4.0-micro, does 9.61. A 3,000-row pass takes 1h39m at the top of that range and 5h12m at the bottom.

Rows per minute on 8 pinned CPU threads

Latency model row_latency = 1200/pp1200 + 1/tg32, from llama-bench -t 8 -p 1200 -n 32 -r 3. A 3,000-row pass takes 1h39m on OLMo-2-1B and 5h12m on granite-4.0-micro. DeBERTa-v3-base reaches its figure only at 512 tokens, its architectural maximum.

Decoder, GGUF Q4_K_M under llama.cppEncoder, dynamic int8
0 40 80 120 160 200 OLMo-2-1B 30.38 Falcon3-1B 27.67 SmolLM2-1.7B 19.35 granite-4.0-1b 18.83 Falcon3-3B 13.68 granite-guardian-3.1-2b 12.45 granite-guardian-3.2-3b-a800m 11.98 SmolLM3-3B 11.40 Phi-4-mini 10.08 Shieldstral (text tower) 9.91 granite-4.0-micro 9.61 DeBERTa-v3-base 186.70 ModernBERT-base 44.60
Table view (every plotted value)
ArmServingRows/minContext tokens3,000-row pass
OLMo-2-1Bdecoder, Q4_K_M30.381,2001h39m
Falcon3-1Bdecoder, Q4_K_M27.671,2001h48m
SmolLM2-1.7Bdecoder, Q4_K_M19.351,2002h35m
granite-4.0-1bdecoder, Q4_K_M18.831,2002h39m
Falcon3-3Bdecoder, Q4_K_M13.681,2003h39m
granite-guardian-3.1-2bdecoder, Q4_K_M12.451,2004h01m
granite-guardian-3.2-3b-a800mdecoder, Q4_K_M11.981,2004h10m
SmolLM3-3Bdecoder, Q4_K_M11.401,2004h23m
Phi-4-minidecoder, Q4_K_M10.081,2004h58m
Shieldstral (text tower)decoder, Q4_K_M9.911,2005h03m
granite-4.0-microdecoder, Q4_K_M9.611,2005h12m
DeBERTa-v3-baseencoder, dynamic int8186.705120h16m
ModernBERT-baseencoder, dynamic int844.601,2001h07m
The host carried foreign load throughout and a real laptop also thermally throttles, so every figure here is an optimistic ceiling. Every value plotted here is read at build time from pinned/laptop-feasibility.json. The table view lists them all.

The encoders are roughly six times faster than the fastest decoder. DeBERTa-v3-base reaches 186.7 rows/min under int8 at 512 tokens, its architectural maximum, so a longer prompt is truncated; the extent on this corpus is on Results. ModernBERT-base does 44.6 rows/min at the full 1,200-token budget.

Caveats on the figures above

The two multimodal arms

Two arms ship a vision tower that a text-only task never uses. Both splits were measured from the checkpoints and the converter output.

Where the parameters sit in the two multimodal arms

Shieldstral is Mistral3ForConditionalGeneration. llama.cpp's converter emits the text tower only for mistral3: 236 tensors, exactly 3,429,006,336 elements, zero vision tensors. The vision side exports separately as an mmproj. gemma-3-4b-it's full checkpoint is 8.0096 GiB, so the split is what makes it loadable on an 8 GiB machine.

Text towerVision towerProjector
0.0 1.0 2.0 3.0 4.0 5.0 Shieldstral-1.0-3B 3.849 B params gemma-3-4b-it 4.300 B params
Table view (every plotted value)
ArmArchitectureText towerVisionProjectorTotalVision plus projector share
Shieldstral-1.0-3BMistral3ForConditionalGeneration3,429,006,336403,305,47216,778,2403,849,090,04810.91%
gemma-3-4b-itGemma3ForConditionalGeneration3,880,263,168416,866,0322,950,2724,300,079,4729.76%
ArtifactBytesGiB
Shieldstral, text-only Q4_K_M on disk2,146,497,3121.9991
Shieldstral, mmproj that is never built840,284,7040.7826
gemma-3-4b-it, full checkpoint8,600,277,8808.0096
Every value plotted here is read at build time from pinned/laptop-feasibility.json. The table view lists them all.

Shieldstral-1.0-3B

Shieldstral is Mistral3ForConditionalGeneration. Its vision tower is 403,305,472 parameters and its projector 16,778,240, so 420,083,712 of its parameters (10.91%) are dead weight for this task. llama.cpp's converter emits only the text tower for mistral3: 236 tensors, exactly 3,429,006,336 elements, matching language_model to the parameter, and zero vision tensors. The text-only Q4_K_M is 2,146,497,312 bytes on disk, 1.9991 GiB. The vision side exports separately as a 840,284,704-byte mmproj that is never built. Its laptop constraint is throughput, at 9.61 rows/min.

gemma-3-4b-it

Its vision tower is 416,866,032 parameters and its projector 2,950,272, so 419,816,304 parameters (9.76%) are dead weight, over a text tower of 3,880,263,168. Its weight bytes total 8,600,277,880, 8.0096 GiB, which is the only arm in the cohort past 8 GiB, so for this arm the split is what makes it loadable on an 8 GiB machine.

Serving settings that carried over

For a scoring-only workload that never generates a token:

Reproducibility of the figures on this page

harness/build_llamacpp.sh builds the CPU benchmarking toolchain, and no script in the harness runs it or writes the CPU results. The measurements were ad-hoc invocations that were never saved to a file. Their logs survive on the studio and the measurement step does not, so the figures on this page are archived and are not reproducible from vendored code. A search of the studio for any script referencing rss_results, max_rss, ru_maxrss, llama-bench or convert_hf_to_gguf found nothing outside llama.cpp itself and the virtual environments.

harness/score_arm.py measures cuda_alloc_gib, elapsed_seconds, rows_per_min and batch duration_ms. It measures no RSS and no CPU latency. Everything on this page came from outside it.

The primitives are staged in pinned/laptop-feasibility.json. Every derived figure on this page is recomputed from them at build time: both 3,000-row pass times, both multimodal parameter shares and every GiB conversion.

Source: benchmarks/EXPERIMENTS.md and benchmarks/slm_toolcall/harness/README.md, staged into pinned/laptop-feasibility.json. Linked from Reproduce.