[GH-ISSUE #710] pip-installing vLLM/torch silently downgrades NCCL below the 2.30.4 floor; import dies at undefined symbol and check_nccl_so() cannot catch it #408

Open
opened 2026-10-26 10:00:12 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @dmvevents on GitHub (Jul 30, 2026).
Original GitHub issue: https://github.com/deepseek-ai/DeepEP/issues/710

Problem

import deep_ep fails with a raw dynamic-linker error after installing vLLM (or anything that pins
torch==2.11.0) into an environment that satisfied the documented NCCL floor:

ImportError: /opt/DeepEP/deep_ep/_C.cpython-312-x86_64-linux-gnu.so: undefined symbol: ncclGetLsaDevicePointer

The chain (each step verified on H200/EFA, deep_ep 2.0.0, torch 2.11.0+cu130, vllm 0.26.0):

  1. The environment starts at nvidia-nccl-cu13==2.30.4 (the README floor: "NCCL 2.30.4 and above").
  2. pip install vllm==0.26.0 pins torch==2.11.0, and torch 2.11.0 pins nvidia-nccl-cu13==2.28.9
    (exact ==) — pip silently downgrades NCCL as a side effect.
  3. NCCL 2.28.x lacks the GIN/LSA device-API symbols _C.so was built against, so the next
    import deep_ep dies at the linker with no version hint.
  4. pip install --no-deps --force-reinstall nvidia-nccl-cu13==2.30.4 fully heals it — deep_ep + vllm
    0.26.0 + torch 2.11.0 then import and run together cleanly.

Why check_nccl_so() cannot catch this case

The guard in deep_ep/__init__.py compares the loaded libnccl.so (from /proc/self/maps) against
the lib at find_nccl_root() — i.e. the NCCL currently installed. A wheel downgrade moves both sides
together
: torch loads 2.28.9 and find_nccl_root() now also resolves to 2.28.9. Loaded == reference, the
guard passes, and the failure surfaces one line later at import deep_ep._C as an opaque linker error.
The invariant that actually broke is "loaded == what _C.so was built against", which the build does
not record anywhere the guard can read.

Suggested fixes (either or both)

  1. Declare the floor in wheel metadata — install_requires=["nvidia-nccl-cu13>=2.30.4"] (per CUDA
    variant). pip would then refuse the torch-driven downgrade loudly instead of performing it silently.
    Today setup.py locates NCCL at build time via find_pkgs.find_nccl_root() but ships no constraint.
  2. Record the built-against NCCL version into the wheel (e.g. write it into the generated envs.py
    next to the existing persistent envs) and extend check_nccl_so() to compare the loaded lib against
    that, so this failure mode produces the guard's existing clear message instead of
    undefined symbol: ....

Environment

  • deep_ep 2.0.0 (wheel built against nvidia-nccl-cu13 2.30.4)
  • torch 2.11.0+cu130, vllm 0.26.0, python 3.12
  • 2× p5en.48xlarge (H200), EFA — though the failure is host-side and hardware-independent

Happy to provide the full install transcript.

Originally created by @dmvevents on GitHub (Jul 30, 2026). Original GitHub issue: https://github.com/deepseek-ai/DeepEP/issues/710 ### Problem `import deep_ep` fails with a raw dynamic-linker error after installing vLLM (or anything that pins `torch==2.11.0`) into an environment that satisfied the documented NCCL floor: ``` ImportError: /opt/DeepEP/deep_ep/_C.cpython-312-x86_64-linux-gnu.so: undefined symbol: ncclGetLsaDevicePointer ``` The chain (each step verified on H200/EFA, deep_ep 2.0.0, torch 2.11.0+cu130, vllm 0.26.0): 1. The environment starts at `nvidia-nccl-cu13==2.30.4` (the README floor: "NCCL 2.30.4 and above"). 2. `pip install vllm==0.26.0` pins `torch==2.11.0`, and **torch 2.11.0 pins `nvidia-nccl-cu13==2.28.9`** (exact `==`) — pip silently downgrades NCCL as a side effect. 3. NCCL 2.28.x lacks the GIN/LSA device-API symbols `_C.so` was built against, so the next `import deep_ep` dies at the linker with no version hint. 4. `pip install --no-deps --force-reinstall nvidia-nccl-cu13==2.30.4` fully heals it — deep_ep + vllm 0.26.0 + torch 2.11.0 then import and run together cleanly. ### Why `check_nccl_so()` cannot catch this case The guard in `deep_ep/__init__.py` compares the **loaded** `libnccl.so` (from `/proc/self/maps`) against the lib at `find_nccl_root()` — i.e. the NCCL **currently installed**. A wheel downgrade moves *both sides together*: torch loads 2.28.9 and `find_nccl_root()` now also resolves to 2.28.9. Loaded == reference, the guard passes, and the failure surfaces one line later at `import deep_ep._C` as an opaque linker error. The invariant that actually broke is "loaded == what `_C.so` was **built** against", which the build does not record anywhere the guard can read. ### Suggested fixes (either or both) 1. **Declare the floor in wheel metadata** — `install_requires=["nvidia-nccl-cu13>=2.30.4"]` (per CUDA variant). pip would then refuse the torch-driven downgrade loudly instead of performing it silently. Today `setup.py` locates NCCL at build time via `find_pkgs.find_nccl_root()` but ships no constraint. 2. **Record the built-against NCCL version into the wheel** (e.g. write it into the generated `envs.py` next to the existing persistent envs) and extend `check_nccl_so()` to compare the loaded lib against *that*, so this failure mode produces the guard's existing clear message instead of `undefined symbol: ...`. ### Environment - deep_ep 2.0.0 (wheel built against nvidia-nccl-cu13 2.30.4) - torch 2.11.0+cu130, vllm 0.26.0, python 3.12 - 2× p5en.48xlarge (H200), EFA — though the failure is host-side and hardware-independent Happy to provide the full install transcript.
Author
Owner

@dmvevents commented on GitHub (Oct 27, 2026):

Checked against the V2.5 source on main @ f6aa38f and the current PyPI metadata. The documented floor is now NCCL 2.32.3 (README.md:53), and the exact pins that trigger the downgrade are still below it:

  • vllm==0.32.0 requires torch==2.13.0, whose Linux x86_64 wheel requires nvidia-nccl-cu13==2.29.7
  • torch==2.14.0 requires nvidia-nccl-cu13==2.30.7

check_nccl_so() (deep_ep/__init__.py:19-41) still compares the loaded library with the one under find_nccl_root(), and the downgrade replaces that one too. setup.py still declares no NCCL requirement. So installing vLLM or torch after DeepEP still moves NCCL below the floor without the guard firing. #712 implements the second suggestion above: it records the build-time NCCL version and rejects older runtimes.

<!-- gh-comment-id:6431482129 --> @dmvevents commented on GitHub (Oct 27, 2026): Checked against the V2.5 source on `main` @ f6aa38f and the current PyPI metadata. The documented floor is now NCCL 2.32.3 (`README.md:53`), and the exact pins that trigger the downgrade are still below it: - `vllm==0.32.0` requires `torch==2.13.0`, whose Linux x86_64 wheel requires `nvidia-nccl-cu13==2.29.7` - `torch==2.14.0` requires `nvidia-nccl-cu13==2.30.7` `check_nccl_so()` (`deep_ep/__init__.py:19-41`) still compares the loaded library with the one under `find_nccl_root()`, and the downgrade replaces that one too. `setup.py` still declares no NCCL requirement. So installing vLLM or torch after DeepEP still moves NCCL below the floor without the guard firing. #712 implements the second suggestion above: it records the build-time NCCL version and rejects older runtimes.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
deepseek-ai/DeepEP#408
No description provided.