Pull requests / #3624
#3624 [Engine] Linux: read the experts from the GGUF with O_DIRECT under STRATA_UNBUFFERED_LOAD=1
open · draft · @akivajp · 0 Kommentare · Auf GitHub
BenchmarksSetup & installServer & APIAMD / HIPNVIDIA / CUDAModels & quantsWindowsLinux
Beschreibung
## Problem and result On Linux, `load_experts_gguf` always reads through the page cache: it `fread`s into a buffer, then `memcpy`s. The Windows branch has an unbuffered reader (`FILE_FLAG_NO_BUFFERING`), but Linux has no equivalent. There, `STRATA_UNBUFFERED_LOAD=1` only raises the reader count to 16, and the load still runs at the page-cache path's speed. On a 3-drive NVMe RAID0 that reads 18.8 GB/s, the expert load holds at ~5.7 GiB/s whatever the reader count. With this change and `STRATA_UNBUFFERED_LOAD=1`, it reads at ~12.0 GiB/s and the server is ready ~4 s sooner. The default path is unchanged. ## Related discussion None: the change is opt-in and leaves the default alone. Related: #3237 (the Linux file tier's choice between the file cache and unbuffered reads). ## Approach A Linux branch that mirrors the Windows one: the same 16-expert reads into a sector-aligned buffer and the same per-expert copies, with `O_DIRECT` in place of `FILE_FLAG_NO_BUFFERING`. It handles short reads and `EINTR`. If the first shard cannot be opened with `O_DIRECT`, it logs this and falls back to the buffered readers. It runs only when `experts_unbuffered()` returns true, which on Linux happens only through `STRATA_UNBUFFERED_LOAD=1`. The buffered code is not touched, and macOS is not affected (`#elif defined(__linux__)`). ## Validation Revision c947561c (on 011c9e60). **Passed:** - Build: `docker build --build-arg CUDA_ARCHITECTURES=89 --build-arg BUILD_VISION=0 --build-arg STRATA_COMMIT=<sha> .`, with no warnings in `expert_source.cpp`. To get the build through, I added `ARG`/`ENV STRATA_COMMIT` to the root Dockerfile's terminal stage locally. That edit is not in this PR (reported separately). - Environment: Ryzen 9 9950X3D, 96 GB RAM, RTX 4090 (`GPU=0`), Ubuntu 26.04.1, kernel 7.0.0-38. btrfs RAID0 over 3 x Crucial T500 2 TB (PCIe 4.0 x4). Qwen3.8-Flash-Next IQ3_S GGUF via `MODEL_PATH`, with `CONTEXT=64k`, `TUNE=skip` and `VISION=off`. - Load speed: the same image, runs alternating. Before each start, I dropped the GGUF's page cache (`posix_fadvise(DONTNEED)`). "Ready" is the time from `docker run` to `/health` 200. | | engine log `loaded 46.84 GiB at` | ready | |---|---|---| | default | 5.72 / 5.65 / 5.69 GiB/s | 19.4 / 17.9 / 17.9 s | | `STRATA_UNBUFFERED_LOAD=1` | 12.01 / 11.97 / 12.04 GiB/s | 13.9 / 14.0 / 13.9 s | - Correctness: with `STRATA_VERIFY_ARENA=1`, both modes print `expert arena checksum 8ae1446c68dc969b (46.84 GiB)`. - The same change on 0.1.45 (477ac13): 5.83–5.95 GiB/s before, 12.04–12.15 GiB/s after, same checksum. **Failed:** none observed. **Not run:** - HIP and SYCL builds: I have no ROCm or oneAPI setup. SYCL has its own `expert_source.cpp`, which this PR does not touch. HIP compiles this file; the new code is POSIX C++ only, but I have not built it, so this PR stays a draft until that is checked. - The fallback when `O_DIRECT` is refused: I had no such filesystem at hand. - A single drive: not measured; I expect a smaller gain. - Decode and prefill speed: not measured. The arena content is identical (same checksum); only the load changes. ## Limits The change is opt-in only. An unbuffered load does not fill the page cache, so a warm restart cannot reuse it. Whether Linux should choose this automatically, as #285 does on Windows, is for you to decide. Raw logs and a small C reproduction of the loader are in https://github.com/akivajp/nvme-raid-bench. The reproduction is `scripts/loader_bench.c`; on the same RAID0, buffered `fread` + `memcpy` gives 5.9 GiB/s and `O_DIRECT` + `memcpy` gives 11.8 GiB/s. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Mehr auf der Site
Links zu Install, Modellen, Releases.