Stabe on DGX Spark with DFlash-NVFP4

#20
by darkmatter2222 - opened
# Laguna S 2.1 NVFP4 — DGX Spark / Portainer Stack v6
# v6 repairs persistent virtual environments that were created without pip.
#
# Import in Portainer:
#   Stacks -> Add stack -> Upload -> select this file -> Deploy the stack
#
# This stack intentionally does NOT use the broken prebuilt vLLM ARM64 image.
# It starts from NVIDIA CUDA 13.0.2, creates a persistent Python 3.12 virtual
# environment, installs vLLM 0.25.1 + the Poolside-recommended FlashInfer
# packages, and then serves the already-downloaded local Laguna model.
#
# First-launch safety settings:
#   - 131,072-token context
#   - 1 concurrent sequence
#   - 70% vLLM memory budget
#   - eager execution (no CUDA graphs / torch.compile)
#   - no speculative decoding
#
# After the model is proven stable, those settings can be increased manually.

services:
  laguna-vllm:
    image: nvidia/cuda:13.0.2-devel-ubuntu24.04
    container_name: laguna-vllm
    hostname: laguna-vllm

    # Keep this disabled for the first validation. After a successful launch,
    # change to "unless-stopped" if automatic restart is desired.
    restart: "no"

    ipc: host
    stop_grace_period: 2m

    ports:
      - "8006:8006"

    environment:
      DEBIAN_FRONTEND: noninteractive
      NVIDIA_VISIBLE_DEVICES: all
      NVIDIA_DRIVER_CAPABILITIES: compute,utility
      CUTE_DSL_ARCH: sm_121a
      MAX_JOBS: "4"
      VIRTUAL_ENV: /opt/vllm025
      PATH: /opt/vllm025/bin:/usr/local/cuda/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True
      HF_HOME: /root/.cache/huggingface
      VLLM_CACHE_ROOT: /root/.cache/vllm
      TORCH_HOME: /root/.cache/torch

    volumes:
      # The model is already downloaded on the DGX Spark.
      - /home/darkmatter2222/models:/home/darkmatter2222/models:ro

      # Persist the installed environment and compilation/download caches.
      - laguna_vllm025_env:/opt/vllm025
      - laguna_huggingface_cache:/root/.cache/huggingface
      - laguna_vllm_cache:/root/.cache/vllm
      - laguna_flashinfer_cache:/root/.cache/flashinfer
      - laguna_torch_cache:/root/.cache/torch

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities:
                - gpu

    ulimits:
      memlock:
        soft: -1
        hard: -1
      stack:
        soft: 67108864
        hard: 67108864

    entrypoint:
      - /bin/bash
      - -lc
      - |
        set -Eeuo pipefail
  
        echo "============================================================"
        echo " Laguna S 2.1 NVFP4 bootstrap"
        echo "============================================================"
        echo "CUDA:"
        nvcc --version || true
        nvidia-smi || true
  
        echo
        echo "[1/4] Installing operating-system prerequisites..."
        apt-get update
        apt-get install -y --no-install-recommends \
          ca-certificates \
          curl \
          git \
          build-essential \
          ninja-build \
          pkg-config \
          libnuma-dev \
          python3.12 \
          python3.12-dev \
          python3.12-venv
        rm -rf /var/lib/apt/lists/*
  
        echo
        echo "[2/4] Creating persistent Python environment..."
        if [ ! -x /opt/vllm025/bin/python ]; then
          python3.12 -m venv /opt/vllm025
        fi

        echo
        echo "[3/4] Repairing pip and installing/updating uv, vLLM 0.25.1, and FlashInfer..."

        if ! /opt/vllm025/bin/python -m pip --version >/dev/null 2>&1; then
          echo "pip is missing from the persistent environment; bootstrapping it with ensurepip..."
          if ! /opt/vllm025/bin/python -m ensurepip --upgrade; then
            echo "ensurepip could not repair the environment; recreating it..."
            rm -rf /opt/vllm025
            python3.12 -m venv /opt/vllm025
          fi
        fi

        /opt/vllm025/bin/python -m pip install \
          --disable-pip-version-check \
          --no-cache-dir \
          --upgrade pip uv

        /opt/vllm025/bin/uv --version

        if ! /opt/vllm025/bin/python -c \
          'import vllm,sys; sys.exit(0 if vllm.__version__ == "0.25.1" else 1)' \
          >/dev/null 2>&1; then
          /opt/vllm025/bin/uv pip install \
            -p /opt/vllm025 \
            "vllm==0.25.1" \
            --torch-backend=cu130
        fi

        if ! /opt/vllm025/bin/python -c \
          'import flashinfer' >/dev/null 2>&1; then
          /opt/vllm025/bin/uv pip install \
            -p /opt/vllm025 \
            "flashinfer-python==0.6.15.dev20260712" \
            "flashinfer-cubin==0.6.15.dev20260712" \
            "flashinfer-jit-cache==0.6.15.dev20260712" \
            --extra-index-url https://flashinfer.ai/whl/nightly/ \
            --extra-index-url https://flashinfer.ai/whl/nightly/cu130/ \
            --index-strategy unsafe-best-match
        fi

        echo
        echo "[4/4] Verifying runtime..."
        /opt/vllm025/bin/python - <<'PY'
        import torch
        import vllm
        import flashinfer
  
        print("Python:", __import__("sys").version)
        print("vLLM:", vllm.__version__)
        print("Torch:", torch.__version__)
        print("CUDA available:", torch.cuda.is_available())
        print("CUDA runtime:", torch.version.cuda)
        print("FlashInfer:", getattr(flashinfer, "__version__", "installed"))
  
        if vllm.__version__ != "0.25.1":
            raise RuntimeError(f"Expected vLLM 0.25.1, found {vllm.__version__}")
        if not torch.cuda.is_available():
            raise RuntimeError("CUDA is not available inside the container")
        PY
  
        if [ ! -f /home/darkmatter2222/models/Laguna-S-2.1-NVFP4/config.json ]; then
          echo "ERROR: Model was not found at /home/darkmatter2222/models/Laguna-S-2.1-NVFP4"
          echo "Check the host bind mount and model directory name."
          exit 10
        fi
  
        echo
        if [ ! -f /home/darkmatter2222/models/Laguna-S-2.1-DFlash-NVFP4/config.json ]; then
          echo "ERROR: DFlash model was not found at:"
          echo "  /home/darkmatter2222/models/Laguna-S-2.1-DFlash-NVFP4"
          exit 11
        fi

        echo
        echo "Starting Laguna S 2.1 with DFlash on port 8006..."
        exec /opt/vllm025/bin/vllm serve /home/darkmatter2222/models/Laguna-S-2.1-NVFP4 \
          --served-model-name laguna-s-2.1 \
          --host 0.0.0.0 \
          --port 8006 \
          --trust-remote-code \
          --dtype auto \
          --safetensors-load-strategy lazy \
          --gpu-memory-utilization 0.70 \
          --max-model-len 262144 \
          --max-num-seqs 4 \
          --max-num-batched-tokens 16384 \
          --enable-prefix-caching \
          --enable-chunked-prefill \
          --enable-auto-tool-choice \
          --tool-call-parser poolside_v1 \
          --reasoning-parser poolside_v1 \
          --override-generation-config '{"temperature":0.7,"top_p":0.95}' \
          --kv-cache-dtype fp8 \
          --speculative-config '{"model":"/home/darkmatter2222/models/Laguna-S-2.1-DFlash-NVFP4","num_speculative_tokens":5,"method":"dflash"}'

    healthcheck:
      test:
        - CMD-SHELL
        - >-
          /opt/vllm025/bin/python -c
          "import urllib.request;
          urllib.request.urlopen('http://127.0.0.1:8006/health', timeout=5)"
      interval: 30s
      timeout: 10s
      retries: 10
      start_period: 30m

volumes:
  laguna_vllm025_env:
  laguna_huggingface_cache:
  laguna_vllm_cache:
  laguna_flashinfer_cache:
  laguna_torch_cache:

Additional Performance Samples

Time Prompt Throughput Generation Throughput Running Waiting GPU KV Cache Prefix Cache Hit Mean Acceptance Length Accepted Throughput Drafted Throughput Draft Acceptance
17:59:58 2.22 15.90 tok/s 64.99 tok/s 24.5%
18:00:08 0.0 tok/s 31.2 tok/s 2 0 28.7% 76.6% 2.40 18.20 tok/s 64.99 tok/s 28.0%
18:00:18 0.0 tok/s 29.8 tok/s 2 0 28.8% 76.6% 2.29 16.80 tok/s 65.00 tok/s 25.8%
18:00:28 0.0 tok/s 29.8 tok/s 1 0 26.4% 76.6% 2.29 16.80 tok/s 64.99 tok/s 25.8%
18:00:38 0.0 tok/s 1.7 tok/s 2 0 46.7% 71.6% 3.40 1.20 tok/s 2.50 tok/s 48.0%
18:00:48 0.0 tok/s 0.1 tok/s 2 1 51.7% 71.6% 1.00 0.00 tok/s 0.50 tok/s 0.0%
18:00:58 0.0 tok/s 0.3 tok/s 2 1 56.7% 71.6% 3.00 0.20 tok/s 0.50 tok/s 40.0%
18:01:08 0.0 tok/s 0.5 tok/s 3 0 66.7% 66.2% 2.50 0.30 tok/s 1.00 tok/s 30.0%
18:01:18 8,538.0 tok/s 0.7 tok/s 3 0 77.0% 66.2% 2.00 0.30 tok/s 1.50 tok/s 20.0%
18:01:28 0.0 tok/s 0.5 tok/s 3 0 82.0% 66.2% 2.50 0.30 tok/s 1.00 tok/s 30.0%
18:01:38 0.0 tok/s 0.5 tok/s 3 0 87.0% 66.2% 2.50 0.30 tok/s 1.00 tok/s 30.0%
18:01:48 10,659.0 tok/s 7.2 tok/s 3 0 85.7% 66.2% 2.15 3.80 tok/s 16.50 tok/s 23.0%
18:01:58 0.0 tok/s 30.7 tok/s 3 0 85.7% 66.2% 2.22 16.90 tok/s 68.99 tok/s 24.5%
18:02:08 0.0 tok/s 11.3 tok/s 2 0 41.4% 62.5% 2.76 7.20 tok/s 20.50 tok/s 35.1%
18:02:18 0.0 tok/s 0.2 tok/s 2 0 51.8% 62.5% 1.00 0.00 tok/s 1.00 tok/s 0.0%
18:02:28 0.0 tok/s 0.4 tok/s 2 0 56.8% 62.5% 4.00 0.30 tok/s 0.50 tok/s 60.0%
18:02:38 8,570.6 tok/s 10.8 tok/s 2 0 53.0% 62.5% 2.49 6.40 tok/s 21.50 tok/s 29.8%
18:02:48 0.0 tok/s 36.6 tok/s 2 0 53.1% 62.5% 2.65 22.80 tok/s 68.99 tok/s 33.0%
18:02:58 0.0 tok/s 33.8 tok/s 1 0 26.6% 62.5% 2.50 20.30 tok/s 67.50 tok/s 30.1%
18:03:08 0.0 tok/s 23.0 tok/s 1 0 26.7% 62.5% 2.53 13.90 tok/s 45.50 tok/s 30.5%
18:03:18 0.0 tok/s 22.6 tok/s 1 0 26.8% 62.5% 2.43 13.30 tok/s 46.50 tok/s 28.6%
18:03:28 0.0 tok/s 24.4 tok/s 1 0 26.8% 62.5% 2.68 15.30 tok/s 45.50 tok/s 33.6%
18:03:38 0.0 tok/s 22.5 tok/s 1 0 26.9% 62.5% 2.47 13.40 tok/s 45.49 tok/s 29.5%

Updated Overall Peak Performance

Metric Previous Peak New Overall Peak
Prompt throughput 10,176.0 tok/s 10,659.0 tok/s
Generation throughput 45.2 tok/s 45.2 tok/s
Accepted speculative throughput 25.40 tok/s 25.40 tok/s
Draft speculative throughput 107.48 tok/s 107.48 tok/s
Mean acceptance length 3.33 tokens 4.00 tokens
Draft acceptance rate 46.7% 60.0%
Prefix-cache hit rate 80.3% 80.3%
GPU KV-cache usage 63.7% 87.0%
Concurrent requests 4 4
Maximum waiting requests 2 2

Updated headline: Peak prompt ingestion increased to 10,659 tokens/s. Peak generation remained 45.2 tokens/s, while the highest observed GPU KV-cache utilization increased to 87.0%. The new samples also recorded a peak speculative mean acceptance length of 4.00 tokens and a 60.0% draft acceptance rate, although both occurred during a very low-volume interval.

image

image

Looping!
image

vLLM's console stats are pretty buggy lately, especially Prompt Throughput. Looks like it bakes up data over time and flushes it all in one second. Also, the peak Draft Acceptance looks artificially high because it happened during a super slow phase (0.30 tok/s), so it's basically based on just one single accepted draft.

Sign up or log in to comment