Skip to content

[Engine] add an opt-in CUDA and HIP hybrid build - #3551

Open
sakuumomo wants to merge 9 commits into
Niko1221:mainfrom
sakuumomo:pr/engine-hybrid-cuda-hip
Open

sakuumomo wants to merge 9 commits into
Niko1221:mainfrom
sakuumomo:pr/engine-hybrid-cuda-hip

Conversation

@sakuumomo

@sakuumomo sakuumomo commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem and result: One process could not use an NVIDIA GPU and an AMD GPU together. STRATA_HYBRID stays off. Turning it on keeps the CUDA host path and compiles the shared kernels again for HIP. Ordinals past the CUDA devices are HIP. The build is Linux x86-64 only. A CUDA-only build and a HIP-only build leave this path out.

A HIP device is named by its architecture, with compute capability left at 0 so it is not read as an NVIDIA architecture. Helpers are every other visible GPU. When hipBLASLt or rocBLAS is present, the HIP copies get the same switches as a pure HIP build, and the HIP prompt kernels use their own device table. When the current device is AMD, startup matches a pure HIP build: the probe accepts a non-gfx11 host, mapped expert fills go through one pinned buffer, the helper busy-waits for its stream, --vram-elastic stays off, and the tail skip, PCIe share, architecture defaults, gfx12 chunk, and pipeline windows follow that card. A HIP primary does not probe the canonical PCIe pack or say that the share will change.

Related discussion: no earlier issue agrees this scope.

Approach: The new files compile only with STRATA_HYBRID. Default builds keep their previous sources and flags. gfx906 is refused at configure. If CMake leaves a configuration's HIP flags empty, the init flags are written back. Two SHELL:-include generator expressions force-include the HIP headers, so CMake does not drop a repeated -include.

STRATA_HYBRID=OFF (default)
  CUDA build, or HIP build, or SYCL build, as before

STRATA_HYBRID=ON (Linux x86-64)
  CUDA host path
  shared kernels compiled again for HIP
  ordinals past the CUDA devices are HIP

Validation:
Passed: four compiles of 10fdcb31 on Linux x86-64. STRATA_BUILD_TESTS=OFF and STRATA_PORTABLE=ON on the Nix builds.
HIP, STRATA_HYBRID off: STRATA_ENABLE_HIP=ON, STRATA_ENABLE_CUDA=OFF, CMAKE_HIP_ARCHITECTURES=gfx1030, STRATA_PREFILL_MMQ=ON, HIP 7.2.3. CMake reported "Strata: HIP enabled, arch gfx1030" and did not report a hybrid build. Output /nix/store/087zqcrh6grkxlkqlmk5hfjm62flfaz5-strata-hip-0.2.1 (strata and strata-device). The compiler printed warnings while compiling for gfx1030. The link finished.
CUDA, STRATA_HYBRID off: STRATA_ENABLE_CUDA=ON, STRATA_ENABLE_HIP=OFF, CMAKE_CUDA_ARCHITECTURES=89-real, STRATA_PREFILL_MMQ=OFF, CUDA 12.9.86, gcc 14.4.0. CMake reported "Strata: CUDA enabled, arch 89-real" and did not report a hybrid build. Output /nix/store/3y0dc0nzihb4plvl8iaj087vw2b4clxm-strata-cuda-0.2.1 (strata and strata-device).
STRATA_HYBRID=ON: the same CUDA flags, plus HIP gfx1150. CMake reported CUDA arch 89-real and "Strata hybrid: gfx1150". The log shows CUDA objects and HIP objects (strata_hip_objs, compiled for gfx1150) in one build. Output /nix/store/h0v2fqhpi910zfx8c148gl828aw12y81-strata-hybrid-0.2.1 (strata and strata-device). The compiler printed warnings while compiling for gfx1150. The link finished.
SYCL: the strata-sycl-dev image from sycl/tools/Dockerfile (oneAPI 2026.1.0, no AOT device). sycl/tools/build.sh strata printed BUILD EXIT 0 and errors: 0. Binary /tmp/strata-wt-hybrid/build-sycl/strata.
The author ran it on two Linux machines and reports that both function as intended. The laptop has an RTX 4060 and a Radeon 890M and serves with STRATA_HYBRID. The desktop has an RX 6800 and an RX 6900 XT and serves with the HIP build, so STRATA_HYBRID stays off there. No command log or timing was attached to that report.
Failed: none observed.
Not run: a SYCL process on a device. A saved log of the laptop startup.

Limits: Linux x86-64 only. A HIP primary refuses --vram-elastic. prime_hw_queues stays on the STRATA_USE_HIP path. Data-type enums are not remapped between the two runtimes. The first host call on an AMD-only process can still enter the CUDA copy before a trampoline is installed. Compute capability 0 sends host code that branches on compute capability down the portable path while a HIP device is current.

Changes since the last update (2026-10-27)

  • Rebased onto upstream main (0.2.6, 4b9e05a2); content re-landed verbatim. New tip b32dee9c — seven commits: the opt-in hybrid build, its 0.2.2/0.2.3 HIP-rule extensions, the hip_compat fixes main's drafter required, and the dsv41 glob guard. The commit hashes in the Validation section belong to the pre-rebase lineage.
  • Equivalent content (the same rebased delta on the owner's deploy branch nixos, pin 3032afd8) has served daily on both machines since the rebase: the laptop as the CUDA+HIP hybrid build (RTX 4060 + Radeon 890M), the desktop as a HIP-only build where STRATA_HYBRID stays off (RX 6800 + RX 6900 XT).
  • Serve-side follow-up PRs are now open in the same stack: [Other] serve: session ladder — conversations survive an engine unload #4306 (session ladder) and [Other] serve+webui: unload that works — pre-staged checkpoints, polite waits, honest answers #4307 (unload that works). Neither touches this diff.

Changes since the last update (2026-10-30)

Branch commits were re-signed (GPG ed25519) on 2026-10-30; trees are unchanged from the validated work.

Dependencies: none — #3553 stacks on this branch.

@sakuumomo
sakuumomo marked this pull request as ready for review October 21, 2026 07:24
bsorensen110 added a commit to bsorensen110/Strata that referenced this pull request Oct 22, 2026
…en the slot pool is VRAM-capped, Niko1221#3441) — integ batch 19 [extern-C hybrid decls beside integ's NVML block]
@sakuumomo
sakuumomo force-pushed the pr/engine-hybrid-cuda-hip branch 2 times, most recently from a1656ff to ca4e5a9 Compare October 25, 2026 19:08
@Niko1221

Copy link
Copy Markdown
Owner

Thank you for the careful work on a combined CUDA and HIP build. It is planned for a later release, with no date yet, and this will stay open until then.

STRATA_HYBRID stays off. Turning it on keeps the CUDA host path and compiles the shared kernels again for HIP. Ordinals past the CUDA devices are HIP. The build is Linux x86-64 only. CUDA-only and HIP-only builds leave this path out.

A HIP device is named by its architecture, with compute capability left at 0. Helpers are every other visible GPU. The HIP copies get the same hipBLASLt and rocBLAS switches as a pure HIP build when those libraries are present, and the HIP prompt kernels use their own device table. When the current device is AMD, startup matches a pure HIP build: the probe accepts a non-gfx11 host, mapped expert fills go through one pinned buffer, the helper busy-waits for its stream, --vram-elastic stays off, and the tail skip, PCIe share, architecture defaults, gfx12 chunk, and pipeline windows follow that card. A HIP primary does not probe the canonical PCIe pack or say that share will change.
… PLE flag and side-thread launch rule, the queue priming, and the integrated-GPU cache reserve
…he dflash2 stream priority and fork defaults, the Strix Halo window cap and the 12 GB card line
rebase-nixos globs every .cu into the hybrid HIP build, and upstream 0.2.3.x
added dsv41 (drafter, vision, exl3 vendor) files that use four APIs the shim
never had to name before: cudaMemcpy2D (ds4_model), cudaDataType and
CUBLAS_GEMM_DEFAULT_TENSOR_OP (the vision and drafter cublasGemmEx calls),
and cudaOccupancyMaxActiveBlocksPerMultiprocessor (exl3). Map each in both
library branches: rocBLAS lets its own kernel selection use the tensor-op
algo, hipBLAS has no algo selection and takes the plain default.

Signed-off-by: Sakurai Momoka <sakumomo@proton.me>
moe_win.cu (vendor, new in 0.2.3.x) passes a small struct by value with
CUDA's read-only marker; HIP passes by-value parameters grid-constant
already, so the attribute only has to disappear.

Signed-off-by: Sakurai Momoka <sakumomo@proton.me>
src/dsv41 (strata-dsv41, STRATA_BUILD_DSV41 OFF by default) is its own
executable: the CUDA lane never compiles it into strata, and its host-side
helpers (ds4_gguf_cpu.cpp, exl3_cpu.cpp, ds4_iq_cpu.cpp) are only linked into
that executable. The hybrid glob compiled every src/*.cu into strata_hip_objs
and whole-archived them into strata, so the HIP copy of ds4_model reached for
those helpers and the link failed. Skip the subtree while the option is off.

Signed-off-by: Sakurai Momoka <sakumomo@proton.me>
…1#3752 (GP100 weight-stationary experts) landed with the 0.2.7 rebase, after this file was written. The kernels are pure PTX (prmt/mad.wide/f16x2 asm): on the CUDA side they are strata_mmq sources only under STRATA_EXPERIMENTAL_SM60, gated at run time to machines whose every GPU is cc 6.0. A hip-src copy of them fails on 'invalid output constraint =f' / 'invalid instruction' in the gfx1150 pass, and could never dispatch on an AMD device - so they belong beside the gdn_chunk/mmq_nvfp4/mmq_kq_lib exclusions. moko flavor build was the witness: moe_ws_down/gu_iq2/gu_iq3 were the only FAILED targets.
@sakuumomo
sakuumomo force-pushed the pr/engine-hybrid-cuda-hip branch from 6424f01 to 5fa2854 Compare October 30, 2026 21:09
The nixos-config flake update moved moko's hybrid build onto CUDA 13.4,
and this lane was the tree's only CUDA 12-era code. libcudart-13.4 has
no cudaDeviceProp::clockRate, so fill_prop failed to compile; guarded,
the strata-device link then failed on the shim's own externs - ld:
undefined reference to cudaGetDeviceProperties_v2 (and the same for
cudaGraphGetEdges_v2 and cudaStreamGetCaptureInfo_v3): CUDA 13 exports
no versioned cudart names and carries the CUDA 12 signatures under the
plain names. An nm audit of every name on the --wrap list against the
shipped libraries (60 cudart names, 8 cublas names) found exactly these
three gone and nothing else; cublas keeps its _v2 API names.
src/core/verify.cpp already flips every call site with
#if CUDART_VERSION >= 13000; this completes the flip for the shim pairs
and the wrap list. The wrap-list half is load-bearing behavior, not just
linkage: wrapped names that no link reference selects would let the 890M's
synthesized device properties, graph edges, and stream-capture routing
bypass the shim silently. cmake 4.4 (nixos-unstable) rejects the bare
list(REPLACE) sub-command, so the swap uses list(TRANSFORM ... REPLACE)
with anchored patterns. HIP-only builds return at the top of hybrid.cmake
and see none of this. Moko's CUDA-13.4 flavor build gate rides with the
nixos-config repin commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants