GitHub ↗
Contents

ZINC#

ZINC (MIT) is a single-binary GGUF engine written in Zig. It has its own kernels for four GPU backends, and serves /health, /v1/models and /v1/chat/completions:

Backend Hardware Build needs
vulkan AMD RDNA (Strix Halo gfx1151), any Vulkan GPU glslc, the Vulkan loader
rocm AMD, HIP ROCm in ROCM_PATH (default /opt/rocm)
cuda NVIDIA Ada sm_89, Blackwell sm_120 CUDA toolkit in CUDA_HOME (default /usr/local/cuda)
metal Apple Silicon Xcode command-line tools

The CUDA backend is how the engine reaches NVIDIA GPUs. It is a C shim over the driver API, NVRTC and cuBLAS (src/cuda/cuda_shim.c). Its int8 GEMMs use __dp4a, the CUDA counterpart of AMD's v_dot4_i32_i8. Upstream's design notes are in third_party/zinc/docs/cuda-backend.md.

The pin#

third_party/zinc is upstream zolotukhin/zinc main at a fixed commit. ZINC changes daily, so the engine builds only the commit it pins, and .github/workflows/bump-zinc.yml moves that pin forward (see "How it stays current").

Build#

git submodule update --init third_party/zinc
scripts/build-zinc.sh ~/.cache/zinc-pin vulkan   # or rocm, cuda
~/.cache/zinc-pin/vulkan/bin/zinc -m model.gguf --prompt "The capital of France is"

The script needs nothing from the system except the backend's own toolkit:

  • Zig. It downloads the Zig release that ZINC's build.zig.zon names as minimum_zig_version (currently 0.15.2) into <prefix>/zig-<version>. The download is checked against the sha256 that ziglang.org publishes.
  • Build output. Zig's caches go under <prefix>, so the submodule stays clean. The binary is <prefix>/<backend>/bin/zinc.

Verified (pin c50b4add, 2026-09-23)#

Backend Result
vulkan builds. Qwen3-0.6B Q4_K_M, prompt 785,6722,315,9625,374: first token 12095 (" Paris"), the same as the NPU lane and the CPU reference. Prefill 817 tok/s; decode 295 tok/s (3.4 ms/tok) with RADV_PERFTEST=coop_matrix, which ZINC expects on RADV.
rocm builds and links the system ROCm 7 (libamdhip64.so.7, libhsa-runtime64). Not run on a model: ZINC's ROCm forward pass implements only the Qwen3.5/3.6 family, and it rejects qwen3 GGUFs with UnsupportedArchitecture.
cuda RTX 5090 (sm_120, rented on Clore.ai; driver 615.71, CUDA 13.2 from NVIDIA's apt repo, CUDA_HOME=/usr/local/cuda-13.2). scripts/build-zinc.sh <prefix> cuda builds. With qwen35-9b-q4k-m (Qwen3.5-9B Q4_K_M, ZINC's catalog) the continuation of "The capital of France is" is " Paris.". Decode 167–173 tok/s (5.8–6.0 ms/tok); prefill 309 tok/s on the 5-token prompt.

ZINC's CUDA and ROCm forward passes share one implementation. It covers only the Qwen3.5/3.6 family: qwen3 GGUFs fail with UnsupportedArchitecture, and Qwen3.5-0.8B (UD-Q4_K_XL) fails with MissingTensor. Vulkan runs qwen3.

ZINC has no BF16 weight path, so use a quantized GGUF. For example, the BF16 golden Qwen3-0.6B-BF16.gguf fails with UnsupportedQuantType (type 30).

Served by 1bit serve#

With -DONEBIT_ZINC=ON (and -DONEBIT_ZINC_BACKEND=vulkan|rocm|cuda, default vulkan), the build runs scripts/build-zinc.sh into build/zinc/, and 1bit serve --device zinc runs that binary (1bit serve):

  • Load. zinc -m <gguf> -p <port> -c <ctx_size> as a private child, with RADV_PERFTEST=coop_matrix unless you already set it, then wait on /health.
  • Requests. Sent without model, because zinc rejects any id except its own. Replies carry the served name.

tests/serve_e2e.sh <1bit> <gguf> zinc passes on Strix Halo: "Paris." under the served name, and streaming. (Before the engine stopped embedding Lemonade, the same launch contract was a local Lemonade recipe, zinc, whose e2e also passed.) zinc's replies carry no timings block, so hosts that read one report 0 tok/s for it.

How it stays current#

.github/workflows/bump-zinc.yml runs daily. When upstream main has moved, it opens a PR that moves third_party/zinc and lists the new upstream commits. It uses the same HRX_BUMP_TOKEN secret as bump-hrx.yml (see HRX + Vulkan). GitHub-hosted CI has no GPU, so before merging a bump, rerun the build and the smoke test above on Strix Halo.

View this page's source on GitHub ↗