Skip to content

torch.compile Triton backend requires libcuda.so even on flagos device #264

Closed

Description

@lvyufeng

Issue Type

  • Bug Report

AI Agent Information

Summary

Qwen3ModelTest::test_generate_compile_model_forward_fullgraph fails on MUSA MTT S5000 because torch.compile() with the Triton backend requires libcuda.so, even when compiling for a non-CUDA device. The test attempts to compile a qwen3 model on the flagos device, but PyTorch's Triton compiler tries to load CUDA libraries unconditionally, causing an import error.

Environment

Click to expand environment details
  • Platform: MUSA (MTT S5000, 8 devices)
  • Python: 3.10.20
  • PyTorch: 2.10.0+cpu
  • torch_fl: commit 2e64a8da6d9d6e81edcfff258f114ce0979fcb19
  • Transformers: 5.16.1

Runtime config:

export TORCH_DEVICE_BACKEND_AUTOLOAD=0
export TRANSFORMERS_TEST_DEVICE_SPEC=hf_device_spec.py
export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1

Reproduction

Run the single test in a fresh process (confirmed reproducible 3/3 runs):

python3 -m pytest \
  "tests/models/qwen3/test_modeling_qwen3.py::Qwen3ModelTest::test_generate_compile_model_forward_fullgraph" \
  -q

Minimal standalone reproducer:

import torch
import torch_fl  # registers the flagos device

model = torch.nn.Linear(10, 10).to("flagos")
compiled_model = torch.compile(model, fullgraph=True)

x = torch.randn(1, 10, device="flagos")
# This will fail during compilation
output = compiled_model(x)

Expected vs Actual Behavior

Expected:
torch.compile() should work on the flagos device without requiring CUDA libraries, either by:

  1. Using a device-agnostic compilation backend
  2. Detecting the target device and skipping CUDA-specific initialization
  3. Providing a fallback compilation path for non-CUDA devices

Actual:

E           OSError: libcuda.so.1: cannot open shared object file: No such file or directory

Full error chain:

torch/_inductor/triton_heuristics.py
  -> import triton
  -> triton.runtime.driver
  -> ctypes.CDLL("libcuda.so.1")
  [fails: libcuda.so.1 not found on MUSA-only system]

Root Cause Analysis

PyTorch's torch.compile() uses the Triton compiler as its default backend. Triton's CUDA driver module unconditionally attempts to load libcuda.so.1 at import time, regardless of the target device. This fails on systems that only have MUSA (or other non-CUDA) accelerators installed.

Why this happens:

  1. torch.compile(model) invokes TorchInductor
  2. TorchInductor imports Triton for kernel generation
  3. Triton's runtime/driver.py loads CUDA driver libraries unconditionally
  4. No CUDA libraries exist on a MUSA-only system → ImportError/OSError

Upstream context:
This is a known limitation in PyTorch + Triton. The Triton compiler was designed primarily for CUDA and does not have a complete device-agnostic abstraction. Recent PyTorch versions are working toward better backend extensibility, but as of PyTorch 2.10, Triton still assumes CUDA availability.

Proposed Solution

Option 1: Skip torch.compile tests on non-CUDA devices (workaround)

@pytest.mark.skipif(
    torch.device("flagos").type != "cuda",
    reason="torch.compile requires CUDA Triton backend"
)
def test_generate_compile_model_forward_fullgraph(self):
    ...

Option 2: Provide a MUSA Triton backend (proper fix)

  • Implement a Triton backend for MUSA that generates MUSA kernels instead of CUDA PTX
  • Register it with PyTorch's compilation backend registry
  • This requires significant engineering effort and deep Triton internals knowledge

Option 3: Use eager mode as fallback

try:
    compiled_model = torch.compile(model)
except (ImportError, OSError):
    compiled_model = model  # fallback to eager

Recommendation:

  • Short-term: Skip torch.compile tests on flagos (Option 1)
  • Long-term: Implement MUSA Triton backend if compilation performance is critical (Option 2)

Verification Plan

  • Decide on approach (skip vs implement backend)
  • If skipping: add appropriate pytest skip marker and verify test is skipped
  • If implementing: verify compiled model runs and produces correct output
  • Re-run test_generate_compile_model_forward_fullgraph and confirm expected behavior

Context & Investigation

Investigation completed:

  1. Isolated this test from the full qwen3 suite (297 tests) and verified it fails deterministically.
  2. Confirmed the error trace leads to Triton's CUDA driver import, not a torch_fl bug.
  3. Checked PyTorch documentation: torch.compile() currently requires CUDA for Triton backend.
  4. Searched for existing issues about torch.compile / Triton / non-CUDA devices — no open duplicate found.
  5. This is a feature gap rather than a torch_fl bug: PyTorch does not support torch.compile() on PrivateUse1 devices without a custom Triton backend.

Related Code Locations

  • PyTorch: torch/_inductor/compile_fx.py — compilation entry point
  • PyTorch: torch/_inductor/codegen/triton.py — Triton code generation
  • Triton: triton/runtime/driver.py — CUDA driver loading (external dependency)
  • torch_fl: would need to implement TritonMUSABackend if pursuing Option 2

Affected Tests

This root cause affects both:

  1. test_generate_compile_model_forward_fullgraph
  2. test_generate_compilation (likely the same error, needs verification)

Checklist - AI Agents MUST Complete All

  • I have provided complete environment information
  • I have included a minimal, self-contained reproducer
  • I have included full error output with traceback
  • I have analyzed the root cause (not just symptoms)
  • I have proposed a specific solution with implementation approach
  • I have identified affected code locations with line numbers
  • I have described how to verify the fix
  • I have checked for duplicate issues
  • All text is in English (required per CLAUDE.md)
  • Code follows project conventions (checked existing code style)

Activity

  1. lvyufeng commented on Sep 24, 2026

    @lvyufeng
    CollaboratorAuthor

    Correcting this thread with measurements taken on the current tree (877afb1).

    The reported error no longer reproduces, and neither proposed fix is the cause

    OSError: libcuda.so.1 was measured at 2e64a8da6d9d6e81edcfff258f114ce0979fcb19. On
    877afb1 the reproducer below still fails, but earlier and differently — and
    Triton is not what fails:

    import torch
    import torch_fl
    
    model = torch.nn.Linear(10, 10).to("flagos")
    compiled_model = torch.compile(model, fullgraph=True)
    print(compiled_model(torch.randn(1, 10, device="flagos")).shape)
    
    # before: AssertionError: Torch not compiled with CUDA enabled
    # after:  OK (1, 10)

    Triton's active driver on this box is MusaDriver (mthreads is_active=True) in
    both arms, so no CUDA driver is ever looked up here. The exception is raised by
    dynamo, not by the compiler:

    torch/_dynamo/utils.py:1708 record_compilation_metrics -> triton.__version__ if has_triton()
    torch/utils/_triton.py:180 is_device_compatible_with_triton
    torch/utils/_triton.py:160 cuda_extra_check -> torch.cuda.current_device()
    torch/cuda/__init__.py -> torch.cuda._lazy_init
    AssertionError: Torch not compiled with CUDA enabled
    

    torch.cuda.current_device() is still stock CPU torch's, because import torch_fl
    did not install the cuda device alias it is supposed to install on a build with
    no CUDA runtime.

    Why the alias did not install

    _alias_cuda_to_flagos() asks torch.cuda.is_available() to decide whether there
    is a real CUDA runtime, and does nothing if there is. That probe has two writers
    in this process:

    1. _phase_vendor_compat() -> _patch_flaggems_philox() ->
      from flag_gems.utils import random_utils -> import flag_gems. FlagGems'
      fused/FLA kernels call torch.flagos.current_device() at module scope, which
      runs flagos._lazy_init(), which reaches torch_fl.compile through
      torch_fl.compile.flagtree_shim, whose module-level _patch_native_cuda_probe()
      sets torch.cuda.is_available = torch.flagos.is_available and saves the replaced
      function as torch.cuda._flagos_original_is_available.
    2. _phase_ecosystem() -> _alias_cuda_to_flagos(), whose guard reads that probe.

    Writer 1 runs a whole phase before writer 2, so the guard read the redirect, saw
    True, and returned early. The function that still knows the answer —
    torch.cuda._flagos_original_is_available — was written and read by nothing.

    Measured after a bare import torch_fl, before -> after #419:

    torch_fl._cuda_alias_active                              False  ->  True
    torch.cuda.current_device is torch.flagos.current_device False  ->  True
    torch.cuda.synchronize is torch.flagos.synchronize       False  ->  True
    torch.device is torch._C.device                          True   ->  False
    torch.device('cuda')                          device(type='cuda') -> device(type='flagos')
    torch.cuda.current_device()   AssertionError: Torch not compiled with CUDA enabled -> 0
    torch.compile(m, fullgraph=True)              same AssertionError -> OK
    

    What this means for the two proposed fixes

    • Option 1 (skip the test on non-CUDA devices) would have hidden a real
      shim defect. Nothing here needs CUDA to compile: with the alias installed,
      torch.compile runs end to end on flagos.
    • Option 2 (a MUSA Triton backend) is not needed for this symptom, and the
      mthreads Triton backend is already the active one on this box.

    The fix is three lines in the guard plus a test, and lands in #419:
    _real_cuda_is_available() reads torch.cuda._flagos_original_is_available
    (falling back to the live probe when nothing redirected it), and the guard calls
    it. No conf, kernel or route changes — where the alias now runs it hands out the
    same flagos device FLAGOS_BACKEND_CONFIG already routed, and the full MUSA
    overload survey's per-overload verdicts are unchanged. FLAGOS_ALIAS_CUDA=0 still
    opts out for anyone who wants device="cuda" to keep failing loudly.

  2. lvyufeng commented on Sep 24, 2026

    @lvyufeng
    CollaboratorAuthor

    Provenance update: re-measured on 17b5d30

    The measurements in the comment above were taken at upstream 877afb1. Upstream
    has since moved to 17b5d30 (#413, #414, #415), so everything above was
    re-run on the rebased tree with the extension rebuilt (torch_fl/lib/libtorch_fl.so
    md5 65020516c7bab18e96ea6f903d6ee3ff). No conclusion in this thread changes:

    • The reproducer still fails on the pre-fix arm with the dynamo
      AssertionError: Torch not compiled with CUDA enabled, and still prints
      OK (1, 10) with the guard fixed.
    • The full 467-overload MUSA survey reports the same summary on both arms with
      zero verdict differences and a case census byte-identical to the pre-rebase run.
    • The unit-suite figures published in fix: ask torch, not the redirected probe, before aliasing cuda to flagos #419 initially understated the pre-fix arm
      (that baseline had not collected the new test file). The corrected pair is
      9 failed, 752 passed, 109 skipped after against 15 failed, 746 passed, 109 skipped before, over the same 870 collected, differing by exactly the new
      file's six tests. The PR body and the operator-support record state the
      corrected numbers.

    Both proposed fixes in this issue remain unnecessary, for the reasons given above.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions