-
Notifications
You must be signed in to change notification settings - Fork 1.6k
fix(multimodal): own NVDEC frame memory and CUDA-gate PyNvVideoCodec in the SGLang image (OPS-8040) #12733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(multimodal): own NVDEC frame memory and CUDA-gate PyNvVideoCodec in the SGLang image (OPS-8040) #12733
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,11 +139,29 @@ RUN --mount=type=bind,source=./container/deps/requirements.common.txt,target=/tm | |
| # Install SGLang-specific runtime dependencies without changing the upstream | ||
| # dependency solution. imageio-ffmpeg is installed from source (no bundled | ||
| # binary) for the VP9 video-encode path; see requirements.sglang.txt. | ||
| {% if device == "cuda" %} | ||
| RUN --mount=type=bind,source=./container/deps/requirements.sglang.txt,target=/tmp/requirements.sglang.txt \ | ||
| --mount=type=cache,target=/root/.cache/pip,sharing=locked \ | ||
| export PIP_CACHE_DIR=/root/.cache/pip && \ | ||
| pip install --break-system-packages --force-reinstall --no-deps \ | ||
| --requirement /tmp/requirements.sglang.txt | ||
| {% else %} | ||
| # PyNvVideoCodec decodes on NVDEC through libnvcuvid, so it is inert on a | ||
| # non-NVIDIA device. Drop it from the shared requirements rather than ship an | ||
| # unusable NVIDIA codec wheel in the Intel XPU image. The pattern is anchored | ||
| # to the line start so it cannot match inside another requirement, and the | ||
| # import check fails the build if the package arrives by another route -- a | ||
| # filter that silently stopped matching would otherwise look like success. | ||
| # Whole-RUN branches rather than a conditional inside one RUN, for the reasons | ||
| # documented at the equivalent block in vllm_runtime.Dockerfile. | ||
| RUN --mount=type=bind,source=./container/deps/requirements.sglang.txt,target=/tmp/requirements.sglang.txt \ | ||
| --mount=type=cache,target=/root/.cache/pip,sharing=locked \ | ||
| export PIP_CACHE_DIR=/root/.cache/pip && \ | ||
| grep -v '^PyNvVideoCodec' /tmp/requirements.sglang.txt > /tmp/requirements.sglang.nonvidia.txt && \ | ||
| pip install --break-system-packages --force-reinstall --no-deps \ | ||
| --requirement /tmp/requirements.sglang.nonvidia.txt && \ | ||
| ! python3 -c "import PyNvVideoCodec" 2>/dev/null | ||
|
Comment on lines
+153
to
+163
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π― Functional Correctness | π Major | β‘ Quick win π§© Analysis chainπ Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target Dockerfile ---'
sed -n '135,175p' container/templates/sglang_runtime.Dockerfile
printf '%s\n' '--- equivalent vLLM block ---'
rg -n -A24 -B8 'PyNvVideoCodec|nonvidia|non-CUDA|non-CUDA' container/templates/vllm_runtime.Dockerfile
printf '%s\n' '--- all relevant references ---'
rg -n 'PyNvVideoCodec|pip show|requirements\.sglang' container container/deps
printf '%s\n' '--- file status ---'
git status --shortRepository: ai-dynamo/dynamo Length of output: 15572 π Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
import os
import pathlib
import subprocess
import sys
import tempfile
with tempfile.TemporaryDirectory() as td:
root = pathlib.Path(td)
site = root / "site"
site.mkdir()
(site / "PyNvVideoCodec").mkdir()
(site / "PyNvVideoCodec" / "__init__.py").write_text(
"raise ImportError('libnvcuvid.so.1: cannot open shared object file')\n"
)
(site / "PyNvVideoCodec-2.2.0.dist-info").mkdir()
(site / "PyNvVideoCodec-2.2.0.dist-info" / "METADATA").write_text(
"Metadata-Version: 2.1\nName: PyNvVideoCodec\nVersion: 2.2.0\n"
)
env = os.environ.copy()
env["PYTHONPATH"] = str(site)
import_result = subprocess.run(
[sys.executable, "-c", "import PyNvVideoCodec"],
env=env, capture_output=True, text=True,
)
show_result = subprocess.run(
[sys.executable, "-m", "pip", "show", "PyNvVideoCodec"],
env=env, capture_output=True, text=True,
)
print("import return code:", import_result.returncode)
print("import stderr contains libnvcuvid:", "libnvcuvid" in import_result.stderr)
print("pip show return code:", show_result.returncode)
print("pip show reports package:", "Name: PyNvVideoCodec" in show_result.stdout)
absent = subprocess.run(
[sys.executable, "-m", "pip", "show", "PyNvVideoCodec"],
env={**os.environ, "PYTHONPATH": str(root / "empty")},
capture_output=True, text=True,
)
print("absent pip show return code:", absent.returncode)
PY
printf '%s\n' '--- SGLang post-install guards ---'
sed -n '365,390p' container/templates/sglang_runtime.Dockerfile
printf '%s\n' '--- SGLang image and device conditions ---'
rg -n -A8 -B8 'sglang|device ==|device !=|base.*image|FROM ' container/templates/sglang_runtime.Dockerfile | head -160Repository: ai-dynamo/dynamo Length of output: 9866 π Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
import pathlib
import subprocess
import sys
import tempfile
import venv
with tempfile.TemporaryDirectory() as td:
env_dir = pathlib.Path(td) / "venv"
venv.EnvBuilder(with_pip=True).create(env_dir)
py = env_dir / "bin" / "python"
site = pathlib.Path(
subprocess.check_output(
[py, "-c", "import sysconfig; print(sysconfig.get_paths()['purelib'])"],
text=True,
).strip()
)
(site / "PyNvVideoCodec").mkdir()
(site / "PyNvVideoCodec" / "__init__.py").write_text(
"raise ImportError('libnvcuvid.so.1: cannot open shared object file')\n"
)
dist = site / "PyNvVideoCodec-2.2.0.dist-info"
dist.mkdir()
(dist / "METADATA").write_text(
"Metadata-Version: 2.1\nName: PyNvVideoCodec\nVersion: 2.2.0\n"
)
import_result = subprocess.run(
[py, "-c", "import PyNvVideoCodec"],
capture_output=True, text=True,
)
show_result = subprocess.run(
[py, "-m", "pip", "show", "PyNvVideoCodec"],
capture_output=True, text=True,
)
negated_import = subprocess.run(
["/bin/sh", "-c", f"! '{py}' -c 'import PyNvVideoCodec' 2>/dev/null"],
capture_output=True, text=True,
)
presence_guard = subprocess.run(
["/bin/sh", "-c",
f"if '{py}' -m pip show PyNvVideoCodec >/dev/null 2>&1; then "
"echo 'ERROR: PyNvVideoCodec is installed in a non-CUDA image' >&2; "
"exit 1; fi"],
capture_output=True, text=True,
)
print("import return code:", import_result.returncode)
print("pip show return code:", show_result.returncode)
print("pip show reports package:", "Name: PyNvVideoCodec" in show_result.stdout)
print("negated import guard return code:", negated_import.returncode)
print("presence guard return code:", presence_guard.returncode)
print("presence guard message:", presence_guard.stderr.strip())
PYRepository: ai-dynamo/dynamo Length of output: 870 π Script executed: #!/bin/bash
set -eu
python3 -m pip show pip >/tmp/pip-show-present.txt
if python3 -m pip show __definitely_missing_pynvvideocode__ >/dev/null 2>&1; then
echo "unexpected package found" >&2
exit 1
fi
printf 'pip show detects an installed distribution: '
grep -q '^Name: pip$' /tmp/pip-show-present.txt && echo yes
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
cat >"$tmpdir/python3" <<'EOF'
#!/bin/sh
exit 1
EOF
chmod +x "$tmpdir/python3"
if PATH="$tmpdir:$PATH" sh -c '! python3 -c "import PyNvVideoCodec" 2>/dev/null'; then
echo "negated import guard passes when import fails"
else
echo "negated import guard failed unexpectedly" >&2
exit 1
fiRepository: ai-dynamo/dynamo Length of output: 192 Make the non-CUDA guard test package presence. π€ Prompt for AI Agents |
||
| {% endif %} | ||
|
|
||
| # Remove the codec-bearing video-DECODE components from the upstream SGLang image | ||
| # (PyAV, decord, OpenCV, torchcodec + any base ffmpeg/libav*), then copy the | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The non-CUDA guard passes when PyNvVideoCodec is installed but cannot import because libnvcuvid is missing, so the XPU image can still ship the unusable wheel. Fix: check module/package presence without importing PyNvVideoCodec.
π€ AI Fix
In container/templates/sglang_runtime.Dockerfile, in the non-CUDA SGLang requirements RUN block, replace
! python3 -c "import PyNvVideoCodec" 2>/dev/nullwithpython3 -c "import importlib.util, sys; sys.exit(importlib.util.find_spec('PyNvVideoCodec') is not None)".