diff --git a/containers/qwentts/entrypoint.sh b/containers/qwentts/entrypoint.sh index 81e5b67..7b7de4f 100644 --- a/containers/qwentts/entrypoint.sh +++ b/containers/qwentts/entrypoint.sh @@ -6,9 +6,32 @@ set -e LOAD="${QWEN_TTS_LOAD:-customvoice,voiceclone}" -echo "=== Qwen3-TTS Server (CPU) ===" +# On ROCm images, torch.cuda.is_available() caches its result for the life +# of the process (PyTorch decorates it with @lru_cache). If /dev/kfd isn't +# fully initialized yet at container start, the very first check can return +# False and the server gets stuck thinking it's CPU-only forever, even +# though the GPU becomes visible moments later. Probe in throwaway +# subprocesses (each gets its own fresh cache) until the GPU is actually +# ready, so the real uvicorn process's first check succeeds. +if [ -e /dev/kfd ]; then + echo "ROCm device detected, waiting for GPU to become available..." + for i in $(seq 1 15); do + if python3 -c "import sys, torch; sys.exit(0 if torch.cuda.is_available() else 1)" 2>/dev/null; then + echo "GPU is available." + break + fi + sleep 1 + done +fi + +DEVICE_REPORT="cpu" +if [ -e /dev/kfd ] && python3 -c "import sys, torch; sys.exit(0 if torch.cuda.is_available() else 1)" 2>/dev/null; then + DEVICE_REPORT="rocm (gpu)" +fi + +echo "=== Qwen3-TTS Server ===" echo "Loading: $LOAD" -echo "Device: cpu" +echo "Device: $DEVICE_REPORT" echo exec uvicorn server:app --host 0.0.0.0 --port 8000 --app-dir /app "$@" diff --git a/containers/qwentts/qwentts.Containerfile b/containers/qwentts/qwentts.Containerfile index 6a5cb22..35acf41 100644 --- a/containers/qwentts/qwentts.Containerfile +++ b/containers/qwentts/qwentts.Containerfile @@ -21,7 +21,7 @@ EXPOSE 8000 # sox (system tool, required at runtime by qwen-tts for audio processing) # ffmpeg (optional but commonly needed for reference-audio format conversion) RUN apt-get update \ - && apt-get install -y --no-install-recommends sox ffmpeg curl \ + && apt-get install -y --no-install-recommends sox ffmpeg curl git \ && apt-get autoremove -y \ && apt-get clean -y \ && rm -rf /var/lib/apt/lists/* @@ -37,6 +37,15 @@ RUN if [ "$DEVICE" = "cpu" ]; then \ # Install qwen-tts and a minimal API server RUN pip install --no-cache-dir qwen-tts fastapi uvicorn python-multipart +# Optional flash-attn for ROCm, built from source (PyPI wheel is CUDA-only); best-effort, skipped on failure +RUN if [ "$DEVICE" = "rocm" ]; then \ + pip install --no-cache-dir ninja \ + && git clone --depth 1 https://github.com/Dao-AILab/flash-attention.git /tmp/flash-attention \ + && (cd /tmp/flash-attention && python setup.py install) \ + || echo "flash-attn build failed or unsupported on this GPU, continuing without it"; \ + rm -rf /tmp/flash-attention; \ + fi + # Models are downloaded at runtime into this directory (mount as a volume # to persist them across container restarts and avoid re-downloading). RUN mkdir -p /app/models diff --git a/containers/qwentts/qwentts.container b/containers/qwentts/qwentts.container index e80dda6..caf24bd 100644 --- a/containers/qwentts/qwentts.container +++ b/containers/qwentts/qwentts.container @@ -11,7 +11,9 @@ ContainerName=qwentts #Memory=8g #CPUs=4 -# ROCm +# ROCm +# Use Triton flash-attn backend (CK backend targets MI200/300, not RDNA consumer cards) +Environment=FLASH_ATTENTION_TRITON_AMD_ENABLE=TRUE AddDevice=/dev/kfd AddDevice=/dev/dri/renderD128 PodmanArgs=--group-add=keep-groups --ipc=host --pids-limit=-1 --security-opt label=disable