build: split CUDA Docker images into cuda12 (12.9.x) / cuda13 (13.3.x), fix Blackwell Ultra arch gate (#23)
The CMakeLists.txt >=12.8 CUDA-architecture branch claimed 121a-real
(Blackwell Ultra) alongside 120a-real, but nvcc from CUDA 12.8.1
rejects compute_121 ("nvcc fatal: Unsupported gpu architecture
'compute_121'"). Confirmed against a real build: 12.8.1 compiles
cleanly with 120a-real but not 121a-real; 12.9.2 compiles both. Split
the >=12.8 branch into >=12.9 (full Blackwell + Ultra) and >=12.8
(Blackwell only, no Ultra).
Since no single CUDA toolkit spans the full arch range -- 12.9.x is
the newest 12.x that still emits Pascal (61-real) SASS, 13.x drops
Pascal entirely but is otherwise more current -- the single :cuda
image can no longer serve both audiences. Split it into two CI
variants, :cuda12 (12.9.2, Pascal through Blackwell Ultra) and
:cuda13 (13.3.1, Turing and newer). The Dockerfile's own --target
cuda stage is unchanged; the CUDA_BUILD_IMAGE/CUDA_RUNTIME_IMAGE ARGs
now default to 12.9.2 (was 12.4.1) and the CI matrix overrides them
per variant.
Both variants were build-tested against nvidia/cuda:12.8.1 and 12.9.2
locally and exercised with real end-to-end synthesis requests on an
actual sm_61 card (GTX 1070 Max-Q) -- RTF ~0.4 on both, no kernel
image / arch mismatch errors.
Co-authored-by: Gary <gitea@gerasch.dev>
This commit is contained in:
@@ -22,7 +22,21 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
variant: [cpu, cuda, vulkan]
|
include:
|
||||||
|
- variant: cpu
|
||||||
|
target: cpu
|
||||||
|
# Two CUDA variants: no single toolkit covers both Pascal and
|
||||||
|
# the newest archs (see CMakeLists.txt).
|
||||||
|
- variant: cuda12
|
||||||
|
target: cuda
|
||||||
|
cuda_build_image: nvidia/cuda:12.9.2-devel-ubuntu22.04
|
||||||
|
cuda_runtime_image: nvidia/cuda:12.9.2-runtime-ubuntu22.04
|
||||||
|
- variant: cuda13
|
||||||
|
target: cuda
|
||||||
|
cuda_build_image: nvidia/cuda:13.3.1-devel-ubuntu22.04
|
||||||
|
cuda_runtime_image: nvidia/cuda:13.3.1-runtime-ubuntu22.04
|
||||||
|
- variant: vulkan
|
||||||
|
target: vulkan
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
@@ -54,12 +68,41 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "tags=${tags}" >> "$GITHUB_OUTPUT"
|
echo "tags=${tags}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# Only set these for the cuda variants, an empty value breaks cpu/vulkan.
|
||||||
|
build_args=""
|
||||||
|
if [ -n "${{ matrix.cuda_build_image }}" ]; then
|
||||||
|
build_args=$'CUDA_BUILD_IMAGE=${{ matrix.cuda_build_image }}\nCUDA_RUNTIME_IMAGE=${{ matrix.cuda_runtime_image }}'
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo "build_args<<BUILD_ARGS_EOF"
|
||||||
|
echo "$build_args"
|
||||||
|
echo "BUILD_ARGS_EOF"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
# GHCR cache tag, read on every run; only pushed to when we're
|
||||||
|
# logged in (not on PR builds).
|
||||||
|
cache_ref="${image}:buildcache-${variant}"
|
||||||
|
cache_from=$'type=gha,scope='"$variant"$'\ntype=registry,ref='"$cache_ref"
|
||||||
|
cache_to="type=gha,mode=max,scope=${variant}"
|
||||||
|
if [ "${{ github.event_name }}" != "pull_request" ]; then
|
||||||
|
cache_to="${cache_to}"$'\n'"type=registry,ref=${cache_ref},mode=max"
|
||||||
|
fi
|
||||||
|
{
|
||||||
|
echo "cache_from<<CACHE_FROM_EOF"
|
||||||
|
echo "$cache_from"
|
||||||
|
echo "CACHE_FROM_EOF"
|
||||||
|
echo "cache_to<<CACHE_TO_EOF"
|
||||||
|
echo "$cache_to"
|
||||||
|
echo "CACHE_TO_EOF"
|
||||||
|
} >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v7
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
target: ${{ matrix.variant }}
|
target: ${{ matrix.target }}
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.tags.outputs.tags }}
|
tags: ${{ steps.tags.outputs.tags }}
|
||||||
cache-from: type=gha,scope=${{ matrix.variant }}
|
build-args: ${{ steps.tags.outputs.build_args }}
|
||||||
cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
|
cache-from: ${{ steps.tags.outputs.cache_from }}
|
||||||
|
cache-to: ${{ steps.tags.outputs.cache_to }}
|
||||||
|
|||||||
+5
-2
@@ -51,14 +51,17 @@ endif()
|
|||||||
# supported card and doesn't need to seed forward JIT compat for anything
|
# supported card and doesn't need to seed forward JIT compat for anything
|
||||||
# older, unlike the 75-virtual baseline which does that for 7.5+. CUDA 13
|
# older, unlike the 75-virtual baseline which does that for 7.5+. CUDA 13
|
||||||
# removed offline compilation for pre-Turing architectures, so 61-real is
|
# removed offline compilation for pre-Turing architectures, so 61-real is
|
||||||
# only emitted on 12.x toolkits; Blackwell (120a/121a) needs 12.8+.
|
# only emitted on 12.x toolkits. Blackwell (120a) needs 12.8+; Blackwell
|
||||||
|
# Ultra (121a) needs 12.9+ (nvcc 12.8 rejects compute_121).
|
||||||
# Users can override with -DCMAKE_CUDA_ARCHITECTURES=native for local builds.
|
# Users can override with -DCMAKE_CUDA_ARCHITECTURES=native for local builds.
|
||||||
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
|
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES)
|
||||||
find_package(CUDAToolkit QUIET)
|
find_package(CUDAToolkit QUIET)
|
||||||
if(CUDAToolkit_FOUND AND CUDAToolkit_VERSION VERSION_GREATER_EQUAL "13.0")
|
if(CUDAToolkit_FOUND AND CUDAToolkit_VERSION VERSION_GREATER_EQUAL "13.0")
|
||||||
set(CMAKE_CUDA_ARCHITECTURES "75-virtual;80-virtual;86-real;89-real;120a-real;121a-real")
|
set(CMAKE_CUDA_ARCHITECTURES "75-virtual;80-virtual;86-real;89-real;120a-real;121a-real")
|
||||||
elseif(CUDAToolkit_FOUND AND CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.8")
|
elseif(CUDAToolkit_FOUND AND CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.9")
|
||||||
set(CMAKE_CUDA_ARCHITECTURES "61-real;75-virtual;80-virtual;86-real;89-real;120a-real;121a-real")
|
set(CMAKE_CUDA_ARCHITECTURES "61-real;75-virtual;80-virtual;86-real;89-real;120a-real;121a-real")
|
||||||
|
elseif(CUDAToolkit_FOUND AND CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.8")
|
||||||
|
set(CMAKE_CUDA_ARCHITECTURES "61-real;75-virtual;80-virtual;86-real;89-real;120a-real")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_CUDA_ARCHITECTURES "61-real;75-virtual;80-virtual;86-real;89-real")
|
set(CMAKE_CUDA_ARCHITECTURES "61-real;75-virtual;80-virtual;86-real;89-real")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
+8
-2
@@ -15,9 +15,15 @@
|
|||||||
# docker build --target cuda -t qwentts.cpp:cuda \
|
# docker build --target cuda -t qwentts.cpp:cuda \
|
||||||
# --build-arg CMAKE_CUDA_ARCHITECTURES=50 . # Maxwell
|
# --build-arg CMAKE_CUDA_ARCHITECTURES=50 . # Maxwell
|
||||||
# See docs/DOCKER.md for details.
|
# See docs/DOCKER.md for details.
|
||||||
|
#
|
||||||
|
# Defaults to the newest CUDA 12.x (widest arch range, see CMakeLists.txt);
|
||||||
|
# override both ARGs for CUDA 13.x instead, as the cuda13 CI variant does:
|
||||||
|
# docker build --target cuda -t qwentts.cpp:cuda13 \
|
||||||
|
# --build-arg CUDA_BUILD_IMAGE=nvidia/cuda:13.3.1-devel-ubuntu22.04 \
|
||||||
|
# --build-arg CUDA_RUNTIME_IMAGE=nvidia/cuda:13.3.1-runtime-ubuntu22.04 .
|
||||||
|
|
||||||
ARG CUDA_BUILD_IMAGE=nvidia/cuda:12.4.1-devel-ubuntu22.04
|
ARG CUDA_BUILD_IMAGE=nvidia/cuda:12.9.2-devel-ubuntu22.04
|
||||||
ARG CUDA_RUNTIME_IMAGE=nvidia/cuda:12.4.1-runtime-ubuntu22.04
|
ARG CUDA_RUNTIME_IMAGE=nvidia/cuda:12.9.2-runtime-ubuntu22.04
|
||||||
|
|
||||||
# ---------------------------------------------------------------- CPU build
|
# ---------------------------------------------------------------- CPU build
|
||||||
FROM ubuntu:22.04 AS build-cpu
|
FROM ubuntu:22.04 AS build-cpu
|
||||||
|
|||||||
+23
-11
@@ -1,9 +1,16 @@
|
|||||||
# Docker
|
# Docker
|
||||||
|
|
||||||
Pre-built images: `ghcr.io/serveurpersocom/qwentts.cpp:cpu`,
|
Pre-built images: `ghcr.io/serveurpersocom/qwentts.cpp:cpu`,
|
||||||
`:cuda` and `:vulkan` (also tagged per release, e.g. `:cuda-v1.2.3`).
|
`:cuda12`, `:cuda13` and `:vulkan` (also tagged per release, e.g.
|
||||||
All three run `tts-server`; `qwen-tts` and `qwen-codec` are included in
|
`:cuda12-v1.2.3`). All four run `tts-server`; `qwen-tts` and
|
||||||
the same image at `/app/`.
|
`qwen-codec` are included in the same image at `/app/`.
|
||||||
|
|
||||||
|
`:cuda12` (CUDA 12.9.x) is built against the widest arch range,
|
||||||
|
Pascal (sm_61) through Blackwell Ultra (120a/121a); `:cuda13`
|
||||||
|
(CUDA 13.3.x) covers Turing and newer only -- upstream dropped
|
||||||
|
offline compilation for pre-Turing architectures in CUDA 13, so a
|
||||||
|
Pascal/Maxwell card needs `:cuda12`. See `CMakeLists.txt` for the
|
||||||
|
full per-toolkit-version arch table.
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run --rm -p 8080:8080 \
|
docker run --rm -p 8080:8080 \
|
||||||
@@ -22,9 +29,12 @@ docker run --rm --gpus all -p 8080:8080 \
|
|||||||
-v /path/to/voices:/voices:ro \
|
-v /path/to/voices:/voices:ro \
|
||||||
-e MODEL_PATH=/models/qwen-talker-1.7b-base-Q8_0.gguf \
|
-e MODEL_PATH=/models/qwen-talker-1.7b-base-Q8_0.gguf \
|
||||||
-e CODEC_PATH=/models/qwen-tokenizer-12hz-Q8_0.gguf \
|
-e CODEC_PATH=/models/qwen-tokenizer-12hz-Q8_0.gguf \
|
||||||
ghcr.io/serveurpersocom/qwentts.cpp:cuda
|
ghcr.io/serveurpersocom/qwentts.cpp:cuda12
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use `:cuda13` instead of `:cuda12` for a newer CUDA toolkit if your
|
||||||
|
card is Turing (sm_75) or newer -- see the note above.
|
||||||
|
|
||||||
Vulkan image (AMD/Intel GPUs), passing through the DRI device node:
|
Vulkan image (AMD/Intel GPUs), passing through the DRI device node:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -36,9 +46,9 @@ docker run --rm --device /dev/dri -p 8080:8080 \
|
|||||||
```
|
```
|
||||||
|
|
||||||
The `:vulkan` image bundles Mesa's Vulkan drivers (AMD/Intel). On an
|
The `:vulkan` image bundles Mesa's Vulkan drivers (AMD/Intel). On an
|
||||||
NVIDIA GPU, prefer `:cuda`; running `:vulkan` there would additionally
|
NVIDIA GPU, prefer `:cuda12` / `:cuda13`; running `:vulkan` there would
|
||||||
need the host's proprietary NVIDIA Vulkan ICD mounted in, which the
|
additionally need the host's proprietary NVIDIA Vulkan ICD mounted in,
|
||||||
image does not provide.
|
which the image does not provide.
|
||||||
|
|
||||||
## Entrypoint environment variables
|
## Entrypoint environment variables
|
||||||
|
|
||||||
@@ -103,10 +113,12 @@ uses the last stage in the `Dockerfile` (`cuda`).
|
|||||||
detect against. This project's own `CMakeLists.txt` already handles
|
detect against. This project's own `CMakeLists.txt` already handles
|
||||||
that by defaulting `CMAKE_CUDA_ARCHITECTURES` to a fixed Pascal-and-newer
|
that by defaulting `CMAKE_CUDA_ARCHITECTURES` to a fixed Pascal-and-newer
|
||||||
list (`61-real;75-virtual;80-virtual;86-real;89-real`, plus Blackwell
|
list (`61-real;75-virtual;80-virtual;86-real;89-real`, plus Blackwell
|
||||||
with CUDA 12.8+) when the variable isn't set, so Pascal cards (sm_61,
|
`120a-real` with CUDA 12.8+ and Blackwell Ultra `121a-real` with CUDA
|
||||||
e.g. the GTX 10-series) work out of the box with no override. GPUs
|
12.9+) when the variable isn't set, so Pascal cards (sm_61, e.g. the
|
||||||
older than Pascal (Maxwell and earlier) still need the architecture
|
GTX 10-series) work out of the box with no override -- as long as the
|
||||||
passed explicitly:
|
toolkit is 12.x (CUDA 13 dropped Pascal offline compilation entirely,
|
||||||
|
see `:cuda13` above). GPUs older than Pascal (Maxwell and earlier)
|
||||||
|
still need the architecture passed explicitly:
|
||||||
|
|
||||||
```
|
```
|
||||||
docker build --target cuda -t qwentts.cpp:cuda \
|
docker build --target cuda -t qwentts.cpp:cuda \
|
||||||
|
|||||||
Reference in New Issue
Block a user