Skip to content

multi device support - #527

Open
mkumargarg wants to merge 4 commits into
mainfrom
my_branch_multi_device_in_single_wheel
Open

mkumargarg wants to merge 4 commits into
mainfrom
my_branch_multi_device_in_single_wheel

Conversation

@mkumargarg

@mkumargarg mkumargarg commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Multi-Device Support - PR #527

Overview

This PR implements multi-architecture wheel support for the sgl-kernel-xpu project, enabling a single wheel to run on multiple Intel GPU architectures (Xe2/BMG and Xe3P/CRI) without requiring separate architecture-specific builds per deployment.

Problem Statement

Previously, each build was architecture-specific due to SYCL_INTEL_TARGET being a compile-time switch that affects common kernel sources. This meant:

  • Separate wheels required for each GPU architecture
  • Complex deployment and dependency management
  • Users had to know their GPU architecture upfront

Solution

Implement a "fat wheel" strategy that:

  1. Builds two separate wheel payloads (one per architecture: _xe20 for BMG, _xe35 for CRI)
  2. Merges them into a single multi-architecture wheel
  3. Uses a runtime architecture probe to dynamically select the correct backend at import time

Key Changes

1. Architecture Detection System

  • include/sgl_arch_query.h (NEW): Unified header shared by probe and torch ops

    • device_architecture(): Gets raw device architecture via SYCL API
    • device_capability(): Maps architecture → (major, minor) version tuple
  • src/arch/sgl_arch_probe.cpp (NEW): Lightweight probe library

    • Built independently of SYCL_INTEL_TARGET
    • Exposes C entry point sgl_probe_device_capability()
    • Installed at package root for dynamic backend selection
  • src/sycl/Device.cpp (REFACTORED):

    • Removed duplicate architecture logic
    • Now delegates to shared sgl_arch_query.h

2. Per-Architecture Package Layout

  • python/sgl_kernel/_xe20/__init__.py (NEW): Xe2/BMG backend stub
  • python/sgl_kernel/_xe35/__init__.py (NEW): Xe3P/CRI backend stub
  • Compiled binaries (*.so) install into respective architecture directories
  • Enables disjoint binary directories for safe merging

3. Runtime Backend Selection

  • python/sgl_kernel/_arch.py (NEW): Architecture detection and backend loader

    • probe_capability(): Calls C probe to get device (major, minor)
    • select_backend(): Maps capability to backend subpackage name
    • load_backend(): Imports and registers architecture-appropriate backend
    • Supports SGL_KERNEL_ARCH env var override for debugging/CI
  • python/sgl_kernel/__init__.py (MODIFIED):

    • Tries direct import first (single-arch builds)
    • Falls back to _arch.load_backend() for multi-arch wheels

4. Wheel Merging Tool

  • scripts/build_fat_wheel.py (NEW): Merges per-architecture wheels
    • Validates disjoint architecture directories
    • Recomputes wheel RECORD manifest
    • Produces canonical wheel filename
    • Includes validation that probe library is present
  • scripts/build_multiarch_wheel.py (NEW): build and merge multiple wheels in single command

5. Build System Updates

  • CMakeLists.txt (MODIFIED):

    • Torch import error detection (missing --no-isolation)
    • SGL_ARCH_PKG_DIR variable controls per-arch install location
  • src/BuildOnLinux.cmake (MODIFIED):

    • Build sgl_arch_probe independently
    • Install to package root (not per-arch)
    • Route common_ops and kernel libraries to per-arch directories

Build & Test Instructions

Building Multi-Architecture Wheel

source /PATH/TO/ONEAPI/setvars.sh

# Pass 1 — Build for Xe2 (BMG)
python -m build --wheel --no-isolation \
  -C build-dir=build \
  -C cmake.define.DPCPP_SYCL_TARGET=bmg \
  -o dist_bmg

# Pass 2 — Build for Xe3P (CRI)
python -m build --wheel --no-isolation \
  -C build-dir=build \
  -C cmake.define.DPCPP_SYCL_TARGET=cri \
  -o dist_cri

# Merge into single multi-architecture wheel
python scripts/build_fat_wheel.py dist_fat dist_bmg/*.whl dist_cri/*.whl


Alternatively, "python scripts/build_multiarch_wheel.py" might be used to do #Pass 1, #Pass 2 and merging of multiple wheel files (BMG and CRI) into single wheel file.

# Install and verify
pip install --force-reinstall dist_fat/*.whl
python -c "import sgl_kernel, sgl_kernel._arch as a; print(a.probe_capability(), a.select_backend())"

@mkumargarg mkumargarg changed the title multi device support (WIP) multi device support Oct 5, 2026
@mkumargarg
mkumargarg force-pushed the my_branch_multi_device_in_single_wheel branch from 7d4aaa9 to 3be21fd Compare October 5, 2026 12:55
@mkumargarg mkumargarg changed the title (WIP) multi device support multi device support Oct 27, 2026
@mkumargarg
mkumargarg marked this pull request as ready for review October 27, 2026 13:52
Copilot AI balanced review requested due to automatic review settings October 27, 2026 13:52
@mkumargarg
mkumargarg force-pushed the my_branch_multi_device_in_single_wheel branch from 1d11d81 to 3a61097 Compare October 27, 2026 13:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The unguarded CRI enum breaks supported older-toolchain builds, and relative output paths can prevent the build helper from locating merged wheels.

2 open issues
What changed in this PR

This PR enables a single sgl-kernel-xpu wheel to support BMG and CRI GPUs by packaging separate architecture backends and selecting one at import time.

Changes:

  • Adds shared architecture detection and runtime backend loading.
  • Moves compiled libraries into per-architecture package directories.
  • Adds scripts to build and merge architecture-specific wheels.
File Description
src/​sycl/​Device.cpp Delegates device queries to the shared helper.
src/​BuildOnLinux.cmake Builds the probe and installs libraries by architecture.
src/​arch/​sgl_arch_probe.cpp Exposes a C entry point for architecture detection.
scripts/​build_multiarch_wheel.py Orchestrates builds, merging, and optional installation.
scripts/​build_fat_wheel.py Merges wheel payloads and regenerates RECORD.
python/​sgl_kernel/​_xe35/​__init__.py Adds the CRI backend package stub.
python/​sgl_kernel/​_xe20/​__init__.py Adds the BMG backend package stub.
python/​sgl_kernel/​_arch.py Detects the architecture and loads its backend.
python/​sgl_kernel/​__init__.py Adds fallback loading for per-architecture backends.
include/​sgl_arch_query.h Centralizes architecture-to-capability mapping.
CMakeLists.txt Selects backend install paths and checks Torch import failures.

Review effort: Balanced

Comment thread include/sgl_arch_query.h
Comment on lines +32 to +33
case syclex::architecture::intel_gpu_cri:
return std::make_tuple(3, 5);
Comment on lines +190 to +191
run([sys.executable, str(MERGE_SCRIPT), str(args.out_dir), *map(str, wheels)])
merged = sorted(args.out_dir.glob("*.whl"))
Signed-off-by: Manoj Kumar <manoj1.kumar@intel.com>
@mkumargarg
mkumargarg force-pushed the my_branch_multi_device_in_single_wheel branch from 3a61097 to 20aa428 Compare October 27, 2026 14:01
 This commit adds a script which clubs many
 commands into one so that user needs to give
 only a single command to generate the multiarch
 wheel.

Signed-off-by: Manoj Kumar <manoj1.kumar@intel.com>

@airMeng airMeng left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the latest revision. The older-toolchain CRI enum guard is fixed, and the actual architecture probe builds with the production CMake/GNU-host path on oneAPI 2026.1 and correctly detects BMG. Requesting changes for the relative output-directory issue described inline, confirming the existing Copilot finding. I reproduced it with actual merger subprocesses and synthetic architecture wheel payloads; an absolute output directory succeeds. Full dual-architecture wheel installation and CRI execution were not tested.

final = wheels[0]
else:
run([sys.executable, str(MERGE_SCRIPT), str(args.out_dir), *map(str, wheels)])
merged = sorted(args.out_dir.glob("*.whl"))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Resolve the output directory before invoking the merger.

run() executes the merger with cwd=PROJECT_ROOT, whereas this glob resolves a relative args.out_dir against the caller's working directory. Invoking python /path/to/repo/scripts/build_multiarch_wheel.py --skip-build --out-dir result from outside the repository creates repo/result/<wheel>.whl, then searches caller/result and exits with expected one merged wheel ... found []; --install is never reached. I confirmed this with the actual merger subprocess: the relative path reproduces the failure and an absolute path succeeds. Please normalize the output directory to an absolute path once and reuse it for merging, discovery and installation.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: args.out_dir (and args.build_dir, which had the same problem with -C build-dir=) are now converted to absolute paths once, right after parse_args(). The merger, the wheel lookup and --install all use that path.

Signed-off-by: Manoj Kumar <manoj1.kumar@intel.com>
Signed-off-by: Manoj Kumar <manoj1.kumar@intel.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants