Skip to content

[NVIDIA] Add opt in CUDA availability check using NVML#10933

Draft
warrendeng wants to merge 1 commit into
triton-lang:mainfrom
warrendeng:nvidia-nvml-cuda-check
Draft

[NVIDIA] Add opt in CUDA availability check using NVML#10933
warrendeng wants to merge 1 commit into
triton-lang:mainfrom
warrendeng:nvidia-nvml-cuda-check

Conversation

@warrendeng

@warrendeng warrendeng commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Context

Triton #9578 changed CudaDriver.is_active() implementation from using torch.cuda.is_available() tocuInit(0). Downstream customers such as vLLM and PyTorch may call CudaDriver.is_active in a parent process before forking a child that later initializes CUDA/calls CudaDriver.is_active() again. Because cuInit(0) poisons the CUDA state of any forked children, the change causes child processes to unable to initialize CUDA.

Examples of this are in vllm-project/vllm#46996 and pytorch/pytorch#189287.

Details

To mitigate the issue, we add an additional path for checking NVIDIA driver status that queries NVML without having to initialize CUDA. We gate this path with env var TRITON_NVML_BASED_CUDA_CHECK=1 and set the var to 0 by default. If this new path fails or if the env var is not set, we fall back to the existing cuInit(0) path.

The default behavior remains unchanged and we continue to preserve Triton's torch-independent runtime path.

Specifically for vLLM, the env var PYTORCH_NVML_BASED_CUDA_CHECK is set to 1 by default. When this is set, torch.cuda.is_available() actually uses NVML instead of cuInit(0) to check driver status. Thus for vLLM, setting our new env var TRITON_NVML_BASED_CUDA_CHECK=1 should have restore behavior prior to #9578 with no other effect.

Test Plan

  • python -m pytest -s --tb=short python/test/unit/runtime/test_driver.py python/test/unit/runtime/test_no_torch_dispatch.py
    • 20 passed
  • Direct Triton probe followed by fork():
    • NVML check enabled: child CUDA initialization passed
    • NVML check unset: existing failure reproduced
  • vLLM import followed by fork(): child CUDA initialization passed
  • Live visibility checks: empty value, ordinal subset, and GPU UUID
  • pre-commit run --from-ref origin/main --to-ref HEAD

@warrendeng warrendeng changed the title [NVIDIA] Add opt-in NVML-based CUDA availability check [NVIDIA] Add opt in CUDA availability check using NVML Jul 17, 2026
return [libdevice_dir, *libcuda_dirs()]


# Adapted from PyTorch's NVML-based CUDA availability check:

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.

these helper functions are equivalent to how PyTorch uses nvml

@warrendeng
warrendeng force-pushed the nvidia-nvml-cuda-check branch 2 times, most recently from 25a55dc to 0af5c91 Compare July 17, 2026 19:10
def is_active():
if os.getenv("TRITON_NVML_BASED_CUDA_CHECK") == "1":
count = _device_count_nvml()
if count >= 0:

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.

if env var is not set or if _device_count_nvml returns -1 (inconclusive) we fall back to old path

Comment thread python/test/unit/runtime/test_driver.py Outdated

def test_cuda_driver_is_active_with_nvml(monkeypatch):
cuda_calls = []
monkeypatch.setenv("TRITON_NVML_BASED_CUDA_CHECK", "1")

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.

Remove this. You can test this with knobs infrastructure. You should add this to the Cuda knobs.

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.

done

Comment thread third_party/nvidia/backend/driver.py Outdated

@staticmethod
def is_active():
if os.getenv("TRITON_NVML_BASED_CUDA_CHECK") == "1":

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.

do we need an env var at all? Can we check nvml and if not there fall back? Wouldn't nvml always be there?


# Adapted from PyTorch's NVML-based CUDA availability check:
# https://github.com/pytorch/pytorch/blob/70d99e998b4955e0049d13a98d77ae1b14db1f45/torch/cuda/__init__.py
def _parse_visible_devices():

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.

this looks quite over-complicated, so we really need all this?

CudaDriver.is_active() calls cuInit(), which initializes CUDA driver state in a parent process and can prevent a subsequently forked child from initializing CUDA.

Add an opt-in NVML probe so callers that need to fork can check NVIDIA device availability without initializing CUDA when NVML returns a conclusive result. Keep the existing CUDA probe as the default and as the fallback for inconclusive NVML checks.
@warrendeng
warrendeng force-pushed the nvidia-nvml-cuda-check branch from 0af5c91 to 7620712 Compare July 17, 2026 20:12

@njriasan njriasan 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.

let's focus on removing all this string parsing.

Comment thread third_party/nvidia/backend/driver.py Outdated

@staticmethod
def is_active():
if os.getenv("TRITON_NVML_BASED_CUDA_CHECK") == "1":

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.

Use knobs here.

return 0
try:
if isinstance(visible_devices[0], str):
if visible_devices[0].startswith("MIG-"):

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.

Is the PyTorch version in C++? We should do this in native code as it could get expensive.


# Adapted from PyTorch's NVML-based CUDA availability check:
# https://github.com/pytorch/pytorch/blob/70d99e998b4955e0049d13a98d77ae1b14db1f45/torch/cuda/__init__.py
def _parse_visible_devices():

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.

Why do we need this much string parsing? Is there not an Nvidia API to get the first device? How do we find a device normally?

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.

3 participants