Repository navigation
Conversation
|
Updated the code and tested with Unsloth's UD-Q4_K_XL with the latest main, works pretty well! |
Engine: - portable.cpp replaces the AVX-only CPU kernels on non-x86; CPU experts, Q2_0 included, run on ggml-cpu's NEON kernels. x86 is unchanged. - cpu_relax.hpp: portable spin-wait and store-fence helpers. - -ffp-contract=off on non-x86, so CPU rounding matches x86 and ggml. - GGML_CPU_ARM_ARCH sets ggml's ARM CPU flags explicitly; gcc's -mcpu=native detects none on the GB10. - Unified memory: the expert cache counts reclaimable memory (MemAvailable minus STRATA_UMA_HEADROOM_GIB, default 6) as free, as NVIDIA's DGX Spark porting guide recommends; cudaMemGetInfo ignores the page cache. setup: - Detect unified memory GPUs from the driver and use system RAM as their memory. - On aarch64, compile the engine with the ARM CPU flags (no prebuilt engine), use NVIDIA's arm64 CUDA repository, and drop the AVX2 requirement. - On unified memory, use --mmap-experts, skip KV streaming, and keep no RAM budget of experts for UD-Q4_K_XL (it would be a second copy beside the GPU cache). Docs: docs/DGX_SPARK.md, linked from the README. Tested on a DGX Spark with IQ2_XS installed by setup: all 24,576 experts on the GPU, prefill 957-1,548 tok/s, decode 56-64 tok/s (2K-74K-token prompts); UD-Q4_K_XL at 262K context: all experts on the GPU (82.2 GiB in all), prefill 590-1,187 tok/s, decode 38-42 tok/s; 60 of 61 ctest tests pass (ple_parity needs a model file not present). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Rebased to latest main, better numbers now. IQ2_XS
UD-Q4_K_XL
Before / After the rebase
|
… its integrated-GPU sizing part From PR #409 (af404df), only device_free_bytes(): on an integrated GPU (cudaDevAttrIntegrated, on HIP hipDeviceAttributeIntegrated; the Ryzen AI Max 8060S) the expert cache sizing and checks count /proc/meminfo MemAvailable less STRATA_UMA_HEADROOM_GIB (6) when that is more than cudaMemGetInfo: the page cache of experts read from the GGUF in place gives way to a device allocation. The PR's aarch64 / DGX Spark CPU parts are not taken. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0154bwiad8gY7wRehCXy27pN
|
Fixed in 0.1.40: the free-memory figure for an integrated GPU (a unified-memory chip such as Strix Halo or the DGX Spark) is now MemAvailable less 6 GiB (STRATA_UMA_HEADROOM_GIB changes it) instead of cudaMemGetInfo's MemFree. The integrated-GPU check is cached per device, so a box with an APU and a discrete card gets the right answer for each. It applies to both backends, on Linux. The aarch64 build break and the rest of the PR are not part of this change. |
|
FYI for Spark users of this branch: on a DGX Spark (GB10) with the branch at 44df8fd, prompts were read at ~90 tok/s (IQ3_S) because the 32 prefill Stager threads inherit the host thread's core-0 pin and yield-spin there. The fix is in the prefill code shared with main (not in this branch's changes): #1056 / #1057 make the waits sleep, and the same binary then reads at ~1,200-1,400 tok/s with ~1 core busy. Thanks for the port, it built and ran first time here. |
… its integrated-GPU sizing part From PR #409 (af404df), only device_free_bytes(): on an integrated GPU (cudaDevAttrIntegrated, on HIP hipDeviceAttributeIntegrated; the Ryzen AI Max 8060S) the expert cache sizing and checks count /proc/meminfo MemAvailable less STRATA_UMA_HEADROOM_GIB (6) when that is more than cudaMemGetInfo: the page cache of experts read from the GGUF in place gives way to a device allocation. The PR's aarch64 / DGX Spark CPU parts are not taken.
…_bytes), its integrated-GPU sizing part From PR Niko1221#409 (af404df), only device_free_bytes(): on an integrated GPU (cudaDevAttrIntegrated, on HIP hipDeviceAttributeIntegrated; the Ryzen AI Max 8060S) the expert cache sizing and checks count /proc/meminfo MemAvailable less STRATA_UMA_HEADROOM_GIB (6) when that is more than cudaMemGetInfo: the page cache of experts read from the GGUF in place gives way to a device allocation. The PR's aarch64 / DGX Spark CPU parts are not taken.
…iko1221#409 review), not in a process-wide static
…_bytes), its integrated-GPU sizing part From PR Niko1221#409 (af404df), only device_free_bytes(): on an integrated GPU (cudaDevAttrIntegrated, on HIP hipDeviceAttributeIntegrated; the Ryzen AI Max 8060S) the expert cache sizing and checks count /proc/meminfo MemAvailable less STRATA_UMA_HEADROOM_GIB (6) when that is more than cudaMemGetInfo: the page cache of experts read from the GGUF in place gives way to a device allocation. The PR's aarch64 / DGX Spark CPU parts are not taken.
…iko1221#409 review), not in a process-wide static
aarch64 / NVIDIA DGX Spark (GB10): build, run and set up with unified memory
This PR makes Strata build and run on aarch64, and
./setup.shwork end to end on an NVIDIA DGX Spark. It is experimental and community-tested, in the same spirit as the AMD HIP and sm_70 builds: one DGX Spark, Qwen3.8-Flash-Next IQ2_XS installed by setup. x86 builds are unchanged.Speed (IQ2_XS, setup's own
run-iq2_xs.sh: 128K context,--kv int8)All 24,576 experts fit in the GPU's expert cache (33.0 GiB), so the CPU computes none.
llama-benchy 0.4.0, 3 runs after a warm-up,
--no-cache, one request at a time, 128 tokens decoded per request. Prefill and decode are from the server log (strata serve: prompt ...). benchy'sppcolumn cannot time Strata's server, because the first stream chunk is sent before the prompt is read; details are indocs/DGX_SPARK.md.What changes
The change splits naturally into three parts. Happy to send them as separate PRs if you prefer.
1. Build and engine on aarch64
src/kernels/cpu/portable.cppreplaces the AVX-only kernel files on non-x86 (CMake chooses byCMAKE_SYSTEM_PROCESSOR). It contains the activation quantizer (expert.cpp's scalar loop) and the BF16 router dot (NEON). The AVX multi-token kernels report themselves unsupported, so native experts use ggml-cpu's NEONvec_dot.q2_own_kernels()). x86 keepsq2_rows_any.include/strata/platform/cpu_relax.hpp:_mm_pause/_mm_sfenceon x86 (as before),yield/dmb oshston aarch64.-ffp-contract=offfor C/C++ on non-x86 GCC/Clang, as an x86 build without-mfmaeffectively has, so host roundings match x86 and ggml. (quantize_act_parity's Q8_K case failed without it.)GGML_CPU_ARM_ARCHturnsGGML_NATIVEoff: gcc's-mcpu=nativefinds no features on GB10's Cortex-X925/A725, which leaves ggml-cpu without dotprod/i8mm.2. Expert cache sizing on unified memory
device_free_bytes()is used by both the cache sizing andExpertCache::open's check. When the driver reports that the GPU shares host memory (cudaDevAttrIntegrated), it countsMemAvailableless 6 GiB (STRATA_UMA_HEADROOM_GIB) as free.cudaMemGetInfocounts only free RAM, and with--mmap-expertsthe page cache is mostly the GGUF's own pages. NVIDIA's DGX Spark Porting Guide (§5.5) recommends the same; swap is not counted.hip_compat:cudaDevAttrIntegrated→hipDeviceAttributeIntegrated.3. setup
CU_DEVICE_ATTRIBUTE_INTEGRATEDvia libcuda, matched to nvidia-smi by PCI address;memory.total [N/A]only as a fallback) and gets the system's RAM as its memory.GGML_CPU_ARM_ARCHfrom/proc/cpuinfo(engine and strata-vision); the CUDA repository key comes fromsbsa;cpu_info()handles the absence of an x86flagsline; no AVX2 requirement.--mmap-experts(an expert arena in RAM would be a second copy of the cache in the same memory) and no KV streaming.Plus
docs/DGX_SPARK.mdand a README pointer next to AMD HIP.Tested on a DGX Spark
./setup.sh --model IQ2_XS --gguf-dir ... --vision no --yes: detects the GB10, compiles, packs, writes the start script.--expert-cache 2048the CPU computed ~22 of ~29 experts per layer, Q2_0 rows included. Output was identical, token for token, to the all-GPU run (18.8 vs 81.9 tok/s).ctest: 51 of 52 pass.ple_parityneeds the Q2_0 model's second shard, which was not present.expert_multi_test(the AVX-512 Q2_0 kernel) is now registered on x86 only.tools/test_setup_*.py: pass, excepttest_setup_choices, which fails the same way on unmodifiedmainon this machine (find_nvcc).test_setup_unslothsimulates an x86 PC and now pinssetup.ARMtoFalse, as it already pins the CPU and GPU.Not covered
--vision): built with the ARM flags, not tested.🤖 Generated with Claude Code