QVAC-24253 feat[api]: expose split-mode 'tensor' in llm-llamacpp - #4121
QVAC-24253 feat[api]: expose split-mode 'tensor' in llm-llamacpp#4121iancris wants to merge 2 commits into
Conversation
Review StatusCurrent Status: ❌ PENDING Pending reviews: Needs 1 Management or Team Lead, and 1 more from Management, Team Lead, or Member. |
License compliance — cleanNo new dependency license findings in this PR. Warn-only (shadow) mode — this check does not block merges yet. Updated automatically by the canonical license compliance workflow. NOTICE presence (advisory)Missing NOTICE (advisory, does not block):
|
f41f5a5 to
45a83e4
Compare
Adds `split-mode: 'tensor'`, selecting qvac-fabric's LLAMA_SPLIT_MODE_TENSOR — meta-device tensor parallelism that splits weights and KV cache across every visible GPU. The enum already exists in the pinned qvac-fabric 10297.0.0, so this is addon-side exposure only: no fabric bump, no registry change. Three fabric constraints are enforced up front with InvalidArgument rather than being left to surface as an opaque native failure: - Flash attention is required; fabric otherwise returns a null context. Both the `flash-attn` and `flash_attn` spellings are checked, because when the caller passes the underscore form none of tuneLoadConfigMap's branches fire and the value is never normalised into the hyphen key. - Auto-fit is unavailable: common_params_fit refuses SPLIT_MODE_TENSOR, and common_fit_params swallows that into a WARN that common_init_result ignores, so the load proceeds unfitted either way. Disabled explicitly and logged at INFO so the logs say what is happening instead of reporting a fit failure. - Some architectures are unsupported. llm_arch_supports_sm_tensor lives in fabric's internal src/llama-arch.h, outside the installed include tree, so the list is mirrored in the addon and pinned by a test that fails if a fabric bump changes it. Fabric's own check remains the backstop. The constraint block sits after tuneLoadConfigMap, not in the GPU branch: that call is what resolves flash-attn, so checking earlier would miss both the default-on and the BitNet-off paths. The row-split probe stays ROW-only — SPLIT_MODE_TENSOR needs no split buffers, and routing it through that probe would silently degrade it to 'layer' on every shipped backend. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Scaffolding, not a change to land. REVERT THIS COMMIT BEFORE MERGING. Adds a vcpkg overlay port pinning qvac-fabric to the head of tetherto/qvac-fabric-llm.cpp#214 ("QVAC-24112 fit: budget against real memory availability", base temp-10297) at 1d14f65, so this PR's split-mode 'tensor' work is compiled and unit-tested against that fit change before either lands. Relevant because tensor mode disables auto-fit, and #214 rewrites how fit budgets device memory. Follows the /rollout-phase-a overlay pattern with one deliberate narrowing: the overlay-ports key is added to packages/llm-llamacpp only, not to all 7 fabric consumers, because only this package needs validating here. The other six keep resolving qvac-fabric from the registry. - vcpkg-overlays/ports/qvac-fabric/{portfile.cmake,vcpkg.json} copied verbatim from the registry port, with REF v${VERSION} replaced by the literal commit (no tag exists for a PR head) and the matching SHA512. - Overlay version is 10297.214.0 rather than the registry's 10297.0.0 so the vcpkg install log distinguishes the two. A silently-wrong overlay path does not error — it falls back to the registry and validates the OLD fabric — so the distinct version is what makes the check honest. default-registry.baseline is deliberately NOT bumped, and the consumer's `version>=` is left at 10297.0.0; the overlay bypasses version resolution and 10297.214.0 satisfies the existing pin either way. Verified locally on macOS arm64: vcpkg reports qvac-fabric[core,gpu-backends,llama]:arm64-osx@10297.214.0 built from source, and addon-test passes 213/213 against it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
45a83e4 to
bf394e8
Compare
|
Addon-side note: moving the tensor-mode Right now the PR disables fit before the remaining config map is converted into llama.cpp args and parsed. Since qvac-fabric exposes Suggested shape: keep the tensor-mode validation where it is if needed for the pre-parser flash-attn/default logic, but either move just the |
|
Could you also add an explicit flash-attention config field to the LLM addon typings, similar to the embedding addon, and propagate it through the SDK schema? Right now For this PR, making flash attention part of the typed LLM surface would make the new tensor-mode requirement much clearer and testable. Please add the LLM addon field(s) ( |
🎯 Problem
@qvac/llm-llamacppships pipeline parallelism (split-mode: 'layer') and accepts the legacy'row'mode, which it degrades to'layer'because no shipped backend provides split buffers. It does not exposeLLAMA_SPLIT_MODE_TENSOR— qvac-fabric's meta-device tensor parallelism, which splits weights and KV cache across every visible GPU.docs/multi-gpu.mdsaid so outright: "CUDA … moved tensor parallelism to a separateLLAMA_SPLIT_MODE_TENSOR, which this package does not expose." So on every backend this package ships, no form of real tensor parallelism was reachable —rowis inert andtensordid not exist.Asana: QVAC-24253
📝 How
2 commits, 14 files — 11 under
packages/llm-llamacpp/, plus 3 of overlay scaffolding.Commit 1 —
15091b91e, the change to landCore (
addon/src/model-interface/LoadFitNormalization.cpp) — parse'tensor'→LLAMA_SPLIT_MODE_TENSOR, plus one consolidated block enforcing what fabric requires of the mode, each rejected up front withInvalidArgumentinstead of surfacing as an opaque native failure:flash-attnandflash_attnspellings are checked; the underscore form is never normalised into the hyphen key when the caller sets it directly, so reading only one would letoffthrough.common_params_fitrefusesSPLIT_MODE_TENSOR, andcommon_fit_paramsswallows that into a WARN thatcommon_init_resultignores, so the load proceeds unfitted either way. Disabling it explicitly makes the logs say what is actually happening. Logged at INFO.llm_arch_supports_sm_tensorlives in fabric's internalsrc/llama-arch.h, outside the installed include tree, so the addon cannot call it. The list is mirrored and pinned by a test that fails if a fabric bump changes it; fabric's own check remains the backstop.Placement — the block sits after
tuneLoadConfigMap, not inside the GPU branch: that call applies the flash-attn defaults (on by default, off for BitNet), so it is the first point where the effective value can be read. It keys onparams.split_mode, so a tensor request that fell back to CPU correctly skips every check.Deliberately unchanged — the row-split probe stays ROW-only.
SPLIT_MODE_TENSORneeds no split buffers; routing it throughgpuBackendSupportsRowSplit()would silently degrade it to'layer'on every shipped backend. A comment and a test pin that.API (additive) —
src/index.tswidens thesplit-modeunion;index.d.tsregenerated.Docs —
docs/multi-gpu.mdretitled "Tensor parallelism is unavailable in shipped builds" → "Two kinds of tensor parallelism" (both anchor links updated), new backend column, decision tree, usage example, fallback rows, strategy table.README.mdconfig table.examples/multiGpuBenchmark.jsgains a fourth mode.Commit 2 —
bf394e8f1, revert before mergePins
qvac-fabricto1d14f65(head of fabric#214, "QVAC-24112 fit: budget against real memory availability") so this PR's tensor work is compiled and tested against that fit change before either lands — relevant because tensor mode disables auto-fit and #214 rewrites how fit budgets device memory.Follows the
/rollout-phase-apattern with one narrowing: theoverlay-portskey is added topackages/llm-llamacpponly, not all 7 fabric consumers.default-registry.baselineis not bumped andversion>=stays at10297.0.0. The overlay version is10297.214.0rather than the registry's10297.0.0on purpose — a wrong overlay path does not error, it silently falls back to the registry and validates the OLD fabric, so the distinct version is what makes the check falsifiable.Not in this PR — multi-host TP over RPC (
GGML_RPCisOFFin the shipped fabric build), changes topackages/model-fit, and performance tuning of the meta backend's all-reduce.🧪 Tested
Base
origin/main@6c495a608. macOS arm64 (M4), Apple clang,BUILD_TESTING=ON, Release — against fabric#214 via the overlay, not the registry version. Overlay confirmed live:qvac-fabric[core,gpu-backends,llama]:arm64-osx@10297.214.0, built from source../addon-test --gtest_filter='*TensorSplit*'— 12/12 pass: parse + fit disabled; fit left enabled for none/layer/row; underscore key and uppercase; row probe not invoked; never degraded;flash-attn: offandflash_attn: offboth rejected; flash-attn on/unset accepted; unsupported architecture rejected by name; supported architecture accepted; CPU fallback clears toNONE; the 30-entry denylist pin; invalid-value error text.LoadFitNormalizationTest.* : LoadFitSnapshotTest.* : TuneConfigMap* : *BackendSelection*— 213/213 pass.npm run typecheck,test:types:consumer,lint:js,lint:ts,check:generated— clean.git-clang-format --diff(the exact commandcpp-lintruns) — clean.Not run locally: the model-level test (needs the multi-GB GGUF set, covered by
cpp-tests) and the two new multi-GPU integration cases (gated onQVAC_HAS_MULTI_GPU=1, which no workflow sets — they need a two-GPU host and remain unexecuted).run-cpp-addon-testsapplied; thecpp-testslane compiles the addon, so the overlay is exercised on darwin-arm64, linux-x64 and windows-x64.None. Purely additive: a new accepted value for an existing optional config key. Existing
split-modevalues behave exactly as before,rowstill degrades tolayer, and the mobile rejection is unchanged.package.jsonuntouched — the version bump and release heading are left to the release flow.The overlay commit is the one thing that must not reach
main; see the banner above.🔌 API Changes
Pinned by a type test asserting
'tensor'is assignable and the union stays closed —test/types/consumer-cjs.test-d.tscarries a@ts-expect-erroron an invalid mode, which stops compiling if the union is ever widened tostring.'tensor'is EXPERIMENTAL and desktop-only. It requires flash attention, disables auto-fit (setctx_sizeexplicitly for large models, or the load can OOM where auto-fit would have trimmed the context), and is unavailable for some architectures. Fabric documents the mode as experimental and expects good performance mainly on multi-GPU CUDA, which this package does not ship — every shipped backend takes the meta backend's generic fallback reduction rather than a tuned all-reduce. Correct, but not assumed faster than'layer'without measurement.🤖 Generated with Claude Code