[GPU] Add initial acceleration for AMD (ROCm 7.2.4, MiGraphX)#752
[GPU] Add initial acceleration for AMD (ROCm 7.2.4, MiGraphX)#752Schaka wants to merge 2 commits into
Conversation
|
There was a problem hiding this comment.
Code Review
This pull request introduces experimental support for AMD GPUs (ROCm / MIGraphX) by adding a dedicated Dockerfile-rocm, a docker-compose configuration, and documentation. It also implements a new faster-whisper transcription backend to bypass MIGraphX's limitations with the ONNX Whisper decoder, and updates ONNX session helpers to support the MIGraphXExecutionProvider. Feedback on these changes highlights a silent package installation failure in the Dockerfile due to a non-existent postgresql-client-18 package, a fragile hardcoded Python version tag (cp312) in the wheel installation step, and a potential unhandled exception during lazy iteration of the transcription generator in whisper_faster.py.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| RUN set -ux; \ | ||
| n=0; \ | ||
| until [ "$n" -ge 5 ]; do \ | ||
| if DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ | ||
| python3 python3-pip python3-venv \ | ||
| libfftw3-double3 libyaml-0-2 libsamplerate0 libsndfile1 \ | ||
| libopenblas0 liblapack3 libgomp1 libpq5 \ | ||
| ffmpeg wget curl supervisor procps \ | ||
| git vim redis-tools strace iputils-ping \ | ||
| postgresql-common ca-certificates tzdata \ | ||
| && /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y \ | ||
| && DEBIAN_FRONTEND=noninteractive apt-get update \ | ||
| && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends postgresql-client-18; then \ | ||
| break; \ | ||
| fi; \ | ||
| n=$((n+1)); \ | ||
| echo "apt-get attempt $n failed - retrying in $((n*n))s"; \ | ||
| sleep $((n*n)); \ | ||
| done; \ | ||
| rm -rf /var/lib/apt/lists/* && \ | ||
| apt-get remove -y python3-numpy || true && \ | ||
| apt-get autoremove -y || true && \ | ||
| rm -f /usr/lib/python3.*/EXTERNALLY-MANAGED |
There was a problem hiding this comment.
The package postgresql-client-18 does not exist (PostgreSQL 17 is the latest stable release, and version 18 is not yet released or packaged). This causes the apt-get install command to fail.
Furthermore, because of how the retry loop is structured, this failure is silently ignored:
- When
apt-get install ... postgresql-client-18fails, theifcondition evaluates to false. - The loop body proceeds to increment
n, print a message, and runsleep $((n*n)). - Since
sleepexits with status0, the loop continues. - After 5 failed attempts, the
untilcondition[ "$n" -ge 5 ]is met, and the loop terminates. - In bash, the exit status of the loop is the exit status of the last command executed in its body, which is
sleep(status0). - The rest of the
RUNinstruction executes, and the Docker build succeeds without actually installingpostgresql-client!
Suggestions:
- Change
postgresql-client-18to a valid version. Since the docker-compose file usespostgres:15-alpine,postgresql-client-15(orpostgresql-client-16/postgresql-client-17) should be used. - Refactor the retry loop to explicitly fail the build if all attempts fail.
RUN set -ux; \
n=0; \
success=false; \
until [ "$n" -ge 5 ]; do \
if DEBIAN_FRONTEND=noninteractive apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
python3 python3-pip python3-venv \
libfftw3-double3 libyaml-0-2 libsamplerate0 libsndfile1 \
libopenblas0 liblapack3 libgomp1 libpq5 \
ffmpeg wget curl supervisor procps \
git vim redis-tools strace iputils-ping \
postgresql-common ca-certificates tzdata \
&& /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y \
&& DEBIAN_FRONTEND=noninteractive apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends postgresql-client-15; then \
success=true; \
break; \
fi; \
n=$((n+1)); \
echo "apt-get attempt $n failed - retrying in $((n*n))s"; \
sleep $((n*n)); \
done; \
if [ "$success" = false ]; then \
echo "Failed to install packages after 5 attempts"; \
exit 1; \
fi; \
rm -rf /var/lib/apt/lists/* && \
apt-get remove -y python3-numpy || true && \
apt-get autoremove -y || true && \
rm -f /usr/lib/python3.*/EXTERNALLY-MANAGED
| whl="$(find ct2whl -name "ctranslate2-${CT2_VERSION}-cp312-cp312-*.whl" | head -1)"; \ | ||
| test -n "$whl"; \ |
There was a problem hiding this comment.
Hardcoding the Python version as cp312 in the wheel filename pattern makes the build fragile if the base image's Python version changes in the future (e.g., if they bump the base image to a newer ROCm/Ubuntu version with Python 3.13). We can dynamically detect the Python version from the virtual environment to make this more robust.
py_ver="$("$VIRTUAL_ENV/bin/python3" -c 'import sys; print(f"cp{sys.version_info.major}{sys.version_info.minor}")')"; \
whl="$(find ct2whl -name "ctranslate2-${CT2_VERSION}-${py_ver}-${py_ver}-*.whl" | head -1)"; \
test -n "$whl";
| for seg in segments: # generator - consuming it runs the decode | ||
| t = (seg.text or "").strip() | ||
| if t: | ||
| texts.append(t) | ||
| lp = getattr(seg, "avg_logprob", None) | ||
| if lp is not None: | ||
| logprobs.append(float(lp)) |
There was a problem hiding this comment.
Since segments returned by model.transcribe is a generator, the actual transcription decoding happens lazily during iteration. Any runtime exception (such as a GPU out-of-memory or CTranslate2 error) will be raised inside this loop. Wrapping the loop in a try...except block allows the transcriber to degrade gracefully and return whatever text was successfully transcribed up to that point, rather than failing the entire transcription task.
| for seg in segments: # generator - consuming it runs the decode | |
| t = (seg.text or "").strip() | |
| if t: | |
| texts.append(t) | |
| lp = getattr(seg, "avg_logprob", None) | |
| if lp is not None: | |
| logprobs.append(float(lp)) | |
| try: | |
| for seg in segments: # generator - consuming it runs the decode | |
| t = (seg.text or "").strip() | |
| if t: | |
| texts.append(t) | |
| lp = getattr(seg, "avg_logprob", None) | |
| if lp is not None: | |
| logprobs.append(float(lp)) | |
| except Exception as exc: | |
| logger.error("Error during faster-whisper transcription decoding: %s", exc) |


AS-IS
AMD GPUs fall back to CPU acceleration for inference
TO-BE
Not everything is GPU-accelerated on AMD:
Essentially, this means some acceleration is achieved, but there's unfortunately still some CPU bottlenecks. I'm not sure they're solveable this point in time.
Test
I ran the deployment YAML I added locally to start a worker. The image builds, the worker is relatively fast on my RX 9070 XT and I confirmed via rocm-smi that it's absolutely using the GPU.
Definitely need some people to test this on different architectures.
Other useful information
I only have the RNDA4 card atm and I'm building with the latest ROCm version. I cannot test older hardware or use an older ROCm base version. So there's a chance this PR isn't good enough to be accepted.
I'm also unsure about building the image. I'm fairly certain building via GitHub CI will fail due to the sheer size of the image. I wasn't able to figure out how you currently build and push your images.
Checklist
Type of change:
Tested on architecture:
Tested on media server:
Updated:
Other:
Related ISSUE: Closes #xx