Repository navigation
Conversation
|
Thanks for the pull request. To keep the tracker readable, every item needs an area prefix in the title and the parts of the pull request template filled in. This one is missing:
Edit the pull request (title and description) and this note goes away on its own. If it is still missing parts in 5 days it will be closed, which is not a rejection: fix it and comment Details: CONTRIBUTING.md |
|
Thanks, this follows the format now. |
…con Metal Support Qwen3.8-Flash-Next Coder variants with 256 experts (including IQ1_M) on Apple Silicon Mac (Metal backend). - metal/kernels/router.metal, moe.metal, prompt.metal: add 256-expert routing and MoE dispatch paths while preserving 512-expert paths for standard models. - metal/src/engine/window.cpp, stream.cpp, stream.h, prompt_chain.inc: dynamically read expert count from model metadata instead of assuming static 512. - metal/src/engine/window.cpp, kernels/dense_mm.metal: guard MetalPerformancePrimitives and add supports_metal4() check to fall back cleanly to decode window prefill on macOS 15 / M1-M4 hardware. - setup.py, metal/setup_mac.py, strata_control/mac_fit.py: add support for family 'coder' and model 'IQ1_M' on macOS.
2550230 to
e145db3
Compare
|
Tested this PR on an M5 Pro (18-core CPU, 20-core GPU, 64 GB, macOS 27.0.1). Hardware that's both M5 and 64 GB isn't covered by docs/MAC.md, so posting the numbers here in case they help with review. Revision: v0.2.4.1 ( PassedNo regression on Q2_0 (same machine, same pack). I alternated four builds: base, PR, base, PR. On each I ran 3 greedy prompts (temperature 0, seed 1, 400 tokens) and the 23 coding-agent turns from
Coder IQ1_M loads and runs on M5:
Long-context recall (
There was no swap at any size, and the engine footprint was about 22 GB. Coding tasks: I ran 2 multi-file Go tasks in an agent loop, graded by hidden tests. Coder passed both (7/7 and 11/11) in about the same time as Q2_0 (11.9 and 5.6 min, against 9.2 and 5.7 min for Q2_0). Tool calls were well formed. The M5 kernels are still used with the new
Failed
Not run
Happy to rerun anything specific on this hardware. |
|
Tested this PR on a Mac where the Coder streams its experts from the SSD: M4 Pro, 48 GB, macOS 27.0.1 (GPU working set 40.2 GB). The two earlier reports were on Macs that keep the model resident (M2 Max 96 GB, M5 Pro 64 GB). Revision: main PassedQ2_0, main vs main+PR (2 rounds, 4 server starts): the answers are byte-identical on all four prompts in every run (3 short prompts and a 3,723-token prompt). Medians, decode tok/s (main / PR): 22.6 / 23.5, 25.1 / 27.2, 26.3 / 29.0; the 3.7K prompt 247 / 295 tok/s. Run-to-run spread on this Mac was larger than the difference (one main run was 13-15% slower on decode and 24% on the long prompt; a 6 MB/s download was running during this A/B). Nothing was swapped out. Coder IQ1_M streams and answers (2 rounds each, the same greedy answers in every run, with and without the copy):
The arena was 13.2-16.8 GB (6,000-7,600 of 12,288 experts), depending on the memory free at start. The copy gave no measurable gain here. Swap: 0 in these runs, 7,332 pages (115 MB) in one later run. Needles ( The 256-expert routing kernels against a CPU reference (a scratch program after Failed
Not run
Small notes: |
…ing expert profile and log prompt path
|
Thank you both for the incredibly thorough and detailed tests on both resident (M5 Pro 64 GB) and streaming (M4 Pro 48 GB) configurations! I have addressed the findings and pushed the fixes in commit 1.
|
Problem and result
Strata previously supported Qwen3.8-Flash-Next 512-expert models on Apple Silicon (Metal), but attempting to run the Qwen3.8-Flash-Next Coder variant (256 experts) failed at multiple levels:
router.metal,moe.metal,prompt.metal) hardcoded 512 experts with 16-unroll routing and MoE dispatches, causing out-of-bounds indexing or shape mismatches when given a 256-expert model.window.cpp,stream.cpp,stream.h,prompt_chain.inc) hardcoded 512 expert slots for routing logits, buffers, and offsets.#include <MetalPerformancePrimitives/MetalPerformancePrimitives.h>was unconditionally included indense_mm.metalwithout feature detection.With this change:
coderfamily andIQ1_Mare supported on Apple Silicon (Metal).Related discussion
none
Approach
router.metal: addedn_expert == 256routing branch (unroll 8) alongside 512 (unroll 16).moe.metal: addedn_expert == 256MoE calculation branch.prompt.metal: addedroute_topk_256kernel specialization.dense_mm.metal&mm_bench.metal: guardedMetalPerformancePrimitivesinclude andgemm_f16with#if __has_include(<MetalPerformancePrimitives/MetalPerformancePrimitives.h>).stream.h,stream.cpp,window.cpp,prompt_chain.inc: replaced static 512 constants withn_expert_detected dynamically from model metadata.window.cpp: addedsupports_metal4()check to fall back cleanly to decode window prefill on M1-M4 / macOS 15 devices.setup.py,metal/setup_mac.py,strata_control/mac_fit.py: enabledcoderfamily andIQ1_Mon macOS, configured shard file naming and profile defaults.metal/tools/stream_experts.py: readn_expertfrom GGUF metadata instead of assuming 512.Validation
Passed:
python3 tools/test_setup_mac.py-> Ran 24 tests in 0.090s, OK.ninja -C build-metal strata-> clean build without errors../build-metal/strata --tokens "100,101...200" --pack <pack> --native <shard1> --ple-gguf <shard2> --expert-profile data/expert-profile-coder.bin --expert-cache 64 --prefill auto --spec 2 --mtp <mtp_dir> --max-context 65536 --mmap-experts --max-new 5Result:
/v1/chat/completions):Failed:
none observed
Not run:
CUDA / ROCm / SYCL execution (change is isolated to Apple Metal backend and macOS setup scripts; non-Mac code paths unaffected).
Limits
On Apple Silicon without Metal 4 (M1-M4, macOS 15), prompt prefill uses the universal decode window batched prefill path; Metal 4 matrix-unit prefill (
matmul2d) requires macOS 26+ and supported hardware.