Weijie Lyu Claude Opus 4.8 (1M context) commited on
Commit
fdba6dc
·
1 Parent(s): 06957f5

Revert cu130 forcing; use ZeroGPU-native cu128 torch + pip cu128 nvcc

Browse files

Root cause found via [GPU-DIAG]: 42 GiB free yet allocation fails --
not a real OOM. The forced cu130 torch is incompatible with ZeroGPU's
fork-based GPU memory management (ZeroGPU targets the cu128 builds of
its supported torch versions). Stop forcing cu130: drop the startup
torch reinstall and the allocator-env band-aids, and run the cu128
torch the base image provides. diff-gaussian then needs a CUDA 12.8
compiler (container only has 13.0), so install nvidia-cuda-nvcc-cu12 /
cccl and point the build's CUDA_HOME at it (arch list incl. sm_120).
Net: fewer hacks than before, aligned with ZeroGPU's supported stack.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +25 -58
  2. requirements.txt +8 -6
app.py CHANGED
@@ -22,59 +22,15 @@ if os.environ.get("HF_HUB_ENABLE_HF_TRANSFER") == "1":
22
  print("⚠️ hf_transfer not available, disabling fast download")
23
  os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "0"
24
 
25
- # ZeroGPU attaches the GPU inside a forked subprocess where NVML can't reinit.
26
- # PyTorch's expandable_segments allocator uses CUDA VMM, whose NVML query then
27
- # asserts ("NVML_SUCCESS == r" in CUDACachingAllocator.cpp). Disabling ONLY
28
- # expandable segments avoids that NVML path while keeping the normal caching
29
- # allocator (so memory is still pooled/reused -- disabling caching entirely OOMs).
30
- # Must be set before torch initializes CUDA, i.e. before "import torch".
31
- os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:False")
32
-
33
  import json
34
  from pathlib import Path
35
  from datetime import datetime
36
  import random
37
 
38
- # -----------------------------
39
- # Ensure a CUDA-13.0 (cu130) torch BEFORE torch is imported.
40
- # The ZeroGPU container ships the CUDA 13.0 toolkit, but the image's torch is a
41
- # cu128 build (torch.version.cuda == "12.8"), so the runtime compile of
42
- # diff-gaussian-rasterization fails with a 13.0-vs-12.8 mismatch. Build-time pip
43
- # kept resolving the cu128 wheel regardless of index config, so fix it here: if
44
- # the installed torch isn't a +cu130 build, reinstall the cu130 stack. This runs
45
- # before "import torch" so the whole process and the build subprocess use cu130.
46
- def _ensure_cu130_torch():
47
- import subprocess as _sp
48
- import sys as _sys
49
- import importlib.metadata as _md
50
- try:
51
- installed = _md.version("torch")
52
- except _md.PackageNotFoundError:
53
- installed = ""
54
- print(f"[CU130-CHECK] installed torch == {installed or '<none>'}")
55
- if "+cu130" in installed:
56
- print("[CU130-CHECK] cu130 torch already present, skipping reinstall")
57
- return
58
- print("[CU130-CHECK] reinstalling torch/torchvision/xformers from the cu130 index...")
59
- # NOT --no-deps: torch 2.11.0+cu130 must pull its matching nvidia-*-cu13 CUDA
60
- # runtime libs. With --no-deps the container kept the base image's nvidia-*-cu12
61
- # (12.8) libs, so cu130 torch ran on cu12 runtime -- a broken mix that made
62
- # allocations fail (surfacing as the NVML/OOM assert). --extra-index-url lets
63
- # torch's non-NVIDIA deps still resolve from PyPI.
64
- _sp.check_call([
65
- _sys.executable, "-m", "pip", "install", "--no-cache-dir",
66
- "--index-url", "https://download.pytorch.org/whl/cu130",
67
- "--extra-index-url", "https://pypi.org/simple",
68
- "torch==2.11.0+cu130", "torchvision==0.26.0+cu130", "xformers==0.0.35",
69
- ])
70
- print("[CU130-CHECK] cu130 stack installed")
71
-
72
- _ensure_cu130_torch()
73
-
74
  import gradio as gr
75
  import numpy as np
76
  import torch
77
- print(f"[CU130-CHECK] torch {torch.__version__} / CUDA {torch.version.cuda}")
78
  import yaml
79
  from easydict import EasyDict as edict
80
  from einops import rearrange
@@ -142,20 +98,31 @@ try:
142
  except ImportError:
143
  print("Installing diff-gaussian-rasterization (compiling for detected CUDA arch)...")
144
  env = os.environ.copy()
145
- try:
146
- import torch as _torch
147
- if _torch.cuda.is_available():
148
- maj, minr = _torch.cuda.get_device_capability()
149
- arch = f"{maj}.{minr}" # e.g., "9.0" on H100/H200, "8.0" on A100
150
- env["TORCH_CUDA_ARCH_LIST"] = f"{arch}+PTX"
151
- else:
152
- # Build stage may not see a GPU on HF Spaces: compile a cross-arch set
153
- env["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6;8.9;9.0+PTX"
154
- except Exception:
155
- env["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6;8.9;9.0+PTX"
156
 
157
- # (Optional) side-step allocator+NVML quirks in restrictive containers
158
- env.setdefault("PYTORCH_NO_CUDA_MEMORY_CACHING", "1")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  # --no-build-isolation: the package's setup.py imports torch to detect the
161
  # CUDA arch, but pip's isolated build env has no torch. Reuse the main env
 
22
  print("⚠️ hf_transfer not available, disabling fast download")
23
  os.environ["HF_HUB_ENABLE_HF_TRANSFER"] = "0"
24
 
 
 
 
 
 
 
 
 
25
  import json
26
  from pathlib import Path
27
  from datetime import datetime
28
  import random
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  import gradio as gr
31
  import numpy as np
32
  import torch
33
+ print(f"[GPU-DIAG] torch {torch.__version__} / CUDA {torch.version.cuda}")
34
  import yaml
35
  from easydict import EasyDict as edict
36
  from einops import rearrange
 
98
  except ImportError:
99
  print("Installing diff-gaussian-rasterization (compiling for detected CUDA arch)...")
100
  env = os.environ.copy()
 
 
 
 
 
 
 
 
 
 
 
101
 
102
+ # Compile against the pip-installed CUDA 12.8 toolkit (nvidia-cuda-nvcc-cu12),
103
+ # NOT the container's CUDA 13.0 toolkit. torch here is the cu128 build ZeroGPU
104
+ # requires, and torch's build check errors on a major CUDA mismatch (nvcc 13 vs
105
+ # torch 12.8). Point CUDA_HOME at the pip nvcc and feed the runtime/cub headers
106
+ # and cudart lib via CPATH/LIBRARY_PATH so nvcc 12.8 matches torch 12.8.
107
+ import site
108
+ _site = site.getsitepackages()[0]
109
+ _nv = os.path.join(_site, "nvidia")
110
+ _nvcc_home = os.path.join(_nv, "cuda_nvcc")
111
+ if os.path.isdir(_nvcc_home):
112
+ env["CUDA_HOME"] = _nvcc_home
113
+ env["PATH"] = os.path.join(_nvcc_home, "bin") + os.pathsep + env.get("PATH", "")
114
+ _incs = [os.path.join(_nv, "cuda_runtime", "include"),
115
+ os.path.join(_nv, "cuda_cccl", "include")]
116
+ env["CPATH"] = os.pathsep.join(_incs + ([env["CPATH"]] if env.get("CPATH") else []))
117
+ _rt_lib = os.path.join(_nv, "cuda_runtime", "lib")
118
+ env["LIBRARY_PATH"] = _rt_lib + os.pathsep + env.get("LIBRARY_PATH", "")
119
+ env["LD_LIBRARY_PATH"] = _rt_lib + os.pathsep + env.get("LD_LIBRARY_PATH", "")
120
+ else:
121
+ print(f"⚠️ pip CUDA toolkit not found at {_nvcc_home}; falling back to system nvcc")
122
+
123
+ # Build a cross-arch set incl. Blackwell sm_120 (the ZeroGPU GPU is cap 12.0);
124
+ # the build stage may not see a GPU, so don't rely on get_device_capability.
125
+ env["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6;8.9;9.0;12.0+PTX"
126
 
127
  # --no-build-isolation: the package's setup.py imports torch to detect the
128
  # CUDA arch, but pip's isolated build env has no torch. Reuse the main env
requirements.txt CHANGED
@@ -1,11 +1,13 @@
1
- # torch 2.11.0 is ZeroGPU-supported (bare version for the config validator) and is
2
- # the version line where torchvision 0.26.0 and xformers 0.0.35 agree (xformers
3
- # 0.0.33 hard-pinned torch==2.9.0, which ZeroGPU rejects; 0.0.35 relaxed to >=2.10).
4
- # The CUDA build matters: the ZeroGPU container ships CUDA 13.0, so torch must be
5
- # cu130 for diff-gaussian-rasterization to compile. Build-time pip resolves the
6
- # cu128 wheel here, so the cu130 reinstall is forced at startup in app.py.
7
  torch==2.11.0
8
  torchvision==0.26.0
 
 
 
 
9
  numpy==1.26.4
10
  pillow==10.4.0
11
  diffusers[torch]==0.30.3
 
1
+ # torch 2.11.0 is ZeroGPU-supported and the version line where torchvision 0.26.0
2
+ # and xformers 0.0.35 agree (xformers 0.0.33 hard-pinned torch==2.9.0, which ZeroGPU
3
+ # rejects; 0.0.35 relaxed to >=2.10). This is the cu128 (CUDA 12.8) build ZeroGPU
4
+ # ships -- required for ZeroGPU's GPU memory management to work.
 
 
5
  torch==2.11.0
6
  torchvision==0.26.0
7
+ # CUDA 12.8 compiler + headers so diff-gaussian-rasterization compiles against a
8
+ # toolkit matching cu128 torch (the container only ships CUDA 13.0). See app.py.
9
+ nvidia-cuda-nvcc-cu12~=12.8.0
10
+ nvidia-cuda-cccl-cu12~=12.8.0
11
  numpy==1.26.4
12
  pillow==10.4.0
13
  diffusers[torch]==0.30.3