Spaces:
Sleeping
Sleeping
| FROM nvidia/cuda:12.1.1-devel-ubuntu22.04 | |
| ENV DEBIAN_FRONTEND=noninteractive | |
| ENV PYTHONUNBUFFERED=1 | |
| ENV OMP_NUM_THREADS=1 | |
| ENV PYTORCH_ALLOC_CONF=expandable_segments:True,max_split_size_mb=128 | |
| ENV ENABLE_CUDNN_BENCHMARK=true | |
| ENV ENABLE_TORCH_COMPILE=false | |
| ENV INFERENCE_TIMEOUT=1800 | |
| ENV MAX_GRADIO_CONCURRENCY=1 | |
| ENV TORCH_CUDA_ARCH_LIST=8.9 | |
| ENV CUDA_HOME=/usr/local/cuda | |
| ENV MPLCONFIGDIR=/tmp/matplotlib | |
| # Cap CUDA-extension build parallelism. mamba_ssm hardcodes 8+ GPU arches | |
| # in setup.py (sm_53..sm_90) which makes the build both memory-heavy AND | |
| # wall-clock heavy on HF Spaces (~16 GB RAM, ~60 min build cap). | |
| # We further patch mamba_ssm below to compile for only sm_89 (L40S target), | |
| # so MAX_JOBS=2 is now safe and ~6x faster than the all-arch serial build. | |
| ENV MAX_JOBS=2 | |
| ENV NVCC_THREADS=2 | |
| RUN apt-get update && apt-get install -y \ | |
| python3.10 \ | |
| python3.10-venv \ | |
| python3-pip \ | |
| git \ | |
| curl \ | |
| build-essential \ | |
| ninja-build \ | |
| libgl1 \ | |
| libglib2.0-0 \ | |
| && rm -rf /var/lib/apt/lists/* | |
| RUN nvcc --version | |
| ENV VENV=/opt/venv | |
| RUN python3.10 -m venv $VENV | |
| ENV PATH="$VENV/bin:$PATH" | |
| RUN pip install --upgrade pip wheel setuptools packaging ninja | |
| RUN pip install --index-url https://download.pytorch.org/whl/cu121 \ | |
| torch torchvision torchaudio | |
| WORKDIR /app | |
| COPY requirements.txt . | |
| RUN pip install --no-cache-dir -r requirements.txt | |
| COPY . . | |
| # Download mamba-ssm source, patch its hardcoded cc_flag list to only build | |
| # for sm_89 (L40S / Ada / RTX 40-series), then install. This avoids HF | |
| # Spaces 60-minute build timeouts when compiling for all 8+ archs serially. | |
| # | |
| # Notes: | |
| # - --no-build-isolation on `pip download` is critical: without it, pip | |
| # spins up a clean build env that tries to fetch torch from PyPI, which | |
| # fails because the cu121 torch wheel only lives on the pytorch.org index. | |
| # - Falls back to a direct PyPI sdist download (curl) if `pip download` | |
| # still misbehaves on this pip/setuptools combination. | |
| COPY scripts/patch_mamba_ssm.py /tmp/patch_mamba_ssm.py | |
| RUN set -eux; \ | |
| mkdir -p /tmp/mamba-src; \ | |
| cd /tmp/mamba-src; \ | |
| if ! pip download "mamba-ssm>=2.2.2" \ | |
| --no-deps --no-binary=:all: --no-build-isolation \ | |
| -d /tmp/mamba-src; then \ | |
| echo "pip download failed; falling back to direct PyPI download"; \ | |
| VER=$(pip index versions mamba-ssm 2>/dev/null \ | |
| | sed -n 's/.*Available versions: \([0-9.]*\).*/\1/p' | head -1 \ | |
| || echo "2.2.2"); \ | |
| curl -fsSLO "https://files.pythonhosted.org/packages/source/m/mamba-ssm/mamba_ssm-${VER}.tar.gz" \ | |
| || curl -fsSLO "https://files.pythonhosted.org/packages/source/m/mamba_ssm/mamba_ssm-${VER}.tar.gz"; \ | |
| fi; \ | |
| SDIST=$(ls mamba_ssm*.tar.gz mamba-ssm*.tar.gz 2>/dev/null | head -1); \ | |
| test -n "$SDIST"; \ | |
| tar -xzf "$SDIST"; \ | |
| SRCDIR=$(tar -tzf "$SDIST" | head -1 | sed 's:/.*::'); \ | |
| cd "$SRCDIR"; \ | |
| python /tmp/patch_mamba_ssm.py setup.py; \ | |
| pip install . --no-build-isolation -v | |
| RUN python - <<'PY' | |
| import torch, sys | |
| print("Torch:", torch.__version__, "CUDA:", torch.version.cuda, "Avail:", torch.cuda.is_available()) | |
| PY | |
| RUN python - <<'PY' | |
| import os | |
| setup_path = 'SRMA-Mamba/selective_scan/setup.py' | |
| with open(setup_path, 'r') as f: | |
| content = f.read() | |
| old_func = '''def get_compute_capability(): | |
| device = torch.device("cuda") | |
| capability = torch.cuda.get_device_capability(device) | |
| return int(str(capability[0]) + str(capability[1]))''' | |
| new_func = '''def get_compute_capability(): | |
| if not torch.cuda.is_available(): | |
| arch_list = os.getenv("TORCH_CUDA_ARCH_LIST", "8.9") | |
| arch = arch_list.split(";")[0].split(",")[0].strip() | |
| if "." in arch: | |
| major, minor = arch.split(".") | |
| return int(major + minor) | |
| else: | |
| return int(arch) | |
| device = torch.device("cuda") | |
| capability = torch.cuda.get_device_capability(device) | |
| return int(str(capability[0]) + str(capability[1]))''' | |
| if old_func in content: | |
| content = content.replace(old_func, new_func) | |
| with open(setup_path, 'w') as f: | |
| f.write(content) | |
| print("Patched setup.py to use TORCH_CUDA_ARCH_LIST when CUDA not available") | |
| else: | |
| print("WARNING: Could not find function to patch") | |
| PY | |
| RUN cd SRMA-Mamba/selective_scan && pip install --no-build-isolation -e . -v | |
| RUN python - <<'PY' | |
| import torch, sys | |
| print("Torch:", torch.__version__, "CUDA:", torch.version.cuda, "Avail:", torch.cuda.is_available()) | |
| import mamba_ssm | |
| print("mamba_ssm OK:", mamba_ssm.__file__) | |
| import selective_scan_cuda_oflex as s | |
| print("selective_scan_cuda_oflex OK:", s.__file__) | |
| print("All CUDA extensions verified successfully.") | |
| PY | |
| EXPOSE 7860 | |
| ENV APP_FILE=app.py | |
| CMD ["sh", "-c", "exec python ${APP_FILE}"] | |