Skip to content

Commit 97bb727

Browse files
fix(pii): install CUDA torch on amd64 so GLiNER can run on GPU (#5552)
* fix(pii): install CUDA torch on amd64 so GLiNER can run on GPU The published pii image installed a CPU-only torch build, so GLiNER on the ECS GPU fleet died at model load with "Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False". The Dockerfile already had a TORCH_INDEX_URL arg, but no CI job ever passed --build-arg, so every image silently took the cpu default. Select the wheel index from TARGETARCH instead: amd64 gets cu128, arm64 keeps the cpu index (cu128 publishes no aarch64 wheel at 2.11.0, and no arm64 target has a GPU). CUDA torch falls back to CPU when no GPU is present, so one image still serves both the Fargate CPU tasks and the EC2 GPU tasks off the same tag — no CI or CDK changes needed. cu128 keeps sm_75, the compute capability of the fleet's T4s, and its CUDA 12.8 runtime needs driver >=525 via minor-version compatibility, which the ECS GPU AMI satisfies. cu121 was not an option: that index stops at torch 2.5.1. Verified in an amd64 build of the changed block: 2.11.0+cu128 cuda=12.8 arch=sm_75 sm_80 sm_86 sm_90 sm_100 sm_120 arm64 still resolves to 2.11.0+cpu. A build-time assert now fails the image if amd64 ever silently regresses to a cpu wheel. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QHNEWVrh7k89m8Wtqzhs18 * fix(pii): assert torch CUDA state after every pip install The check sat directly after the torch install, but requirements-gliner.txt and requirements-dev.txt are installed afterwards and resolve against PyPI with no torch pin, so a future gliner bump could swap the wheel that torch_index selected without tripping the assert. Neither file changes torch today (verified: torch is 2.11.0+cu128 both before and after the gliner install), so this guards the invariant rather than fixing a live regression. Moving it below the last pip install makes it certify the torch that actually ships. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QHNEWVrh7k89m8Wtqzhs18 --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f0d85cb commit 97bb727

1 file changed

Lines changed: 30 additions & 6 deletions

File tree

docker/pii.Dockerfile

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
# gliner package, and the baked GLiNER weights all ship in it, so flipping
77
# engines never requires an image swap.
88
#
9-
# GPU variant (EC2-GPU fleet follow-up): same Dockerfile, CUDA torch wheels —
10-
# docker build --build-arg TORCH_INDEX_URL=https://download.pytorch.org/whl/cu128 ...
11-
# (torch CUDA wheels bundle their own CUDA libs; the host only needs the
12-
# nvidia container runtime.)
9+
# ONE image also serves both fleets: the amd64 build ships CUDA torch, which
10+
# falls back to CPU when no GPU is present, so the Fargate CPU tasks and the
11+
# EC2-GPU tasks pull the same tag. (torch CUDA wheels bundle their own CUDA
12+
# libs; the host only needs the nvidia driver + container runtime.)
1313
#
1414
# Source files are COPY'd last so code edits never re-download deps or models.
1515
# ========================================
@@ -47,10 +47,25 @@ RUN --mount=type=cache,target=/root/.cache/pip \
4747
# torch is pinned here (not requirements-gliner.txt) because the CPU and CUDA
4848
# builds install the same version from different wheel indexes. 2.11.0 is the
4949
# newest release published on both the cpu and cu128 indexes for py312.
50+
#
51+
# cu128's arch list keeps sm_75, the compute capability of the GPU fleet's T4s.
52+
# cu121 could not serve this pin anyway — that index stops at torch 2.5.1.
53+
# CUDA 12.8 needs an NVIDIA driver >=525 via minor-version compatibility, which
54+
# the ECS GPU AMI's nvidia-driver-latest-dkms satisfies.
55+
#
56+
# arm64 takes the cpu index: cu128 publishes no aarch64 wheel at 2.11.0, and no
57+
# arm64 target has a GPU.
5058
ARG TORCH_VERSION=2.11.0
51-
ARG TORCH_INDEX_URL=https://download.pytorch.org/whl/cpu
59+
ARG TORCH_CUDA_INDEX_URL=https://download.pytorch.org/whl/cu128
60+
ARG TORCH_CPU_INDEX_URL=https://download.pytorch.org/whl/cpu
61+
ARG TARGETARCH
5262
RUN --mount=type=cache,target=/root/.cache/pip \
53-
pip install torch==${TORCH_VERSION} --index-url ${TORCH_INDEX_URL}
63+
case "${TARGETARCH}" in \
64+
amd64) torch_index="${TORCH_CUDA_INDEX_URL}" ;; \
65+
arm64) torch_index="${TORCH_CPU_INDEX_URL}" ;; \
66+
*) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
67+
esac && \
68+
pip install torch==${TORCH_VERSION} --index-url "${torch_index}"
5469

5570
COPY apps/pii/requirements-gliner.txt ./requirements-gliner.txt
5671
RUN --mount=type=cache,target=/root/.cache/pip \
@@ -84,6 +99,15 @@ COPY apps/pii/requirements-dev.txt ./requirements-dev.txt
8499
RUN --mount=type=cache,target=/root/.cache/pip \
85100
pip install -r requirements-dev.txt
86101

102+
# Runs after every pip install, because the requirements above resolve against
103+
# PyPI and could swap the wheel torch_index chose. A cpu-only torch on amd64
104+
# otherwise surfaces only as "torch.cuda.is_available() is False" once GLiNER
105+
# loads on a GPU host.
106+
RUN python -c "import torch; \
107+
have = torch.version.cuda is not None; \
108+
want = '${TARGETARCH}' == 'amd64'; \
109+
assert have == want, f'{torch.__version__}: cuda build={have}, expected={want}'"
110+
87111
RUN groupadd -g 1001 pii && \
88112
useradd -u 1001 -g pii pii && \
89113
chown -R pii:pii /app

0 commit comments

Comments
 (0)