fix(pii): install CUDA torch on amd64 so GLiNER can run on GPU#5552
Conversation
|
@greptile review |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview
After all Tradeoff: larger amd64 image (~+3–4 GB installed) in exchange for a single image workflow. Reviewed by Cursor Bugbot for commit d088912. Bugbot is set up for automated code reviews on this repo. Configure here. |
Greptile SummaryThis PR updates the PII Docker image so GLiNER can use CUDA torch on amd64 builds. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (4): Last reviewed commit: "fix(pii): assert torch CUDA state after ..." | Re-trigger Greptile |
| ARG TARGETARCH | ||
| RUN --mount=type=cache,target=/root/.cache/pip \ | ||
| pip install torch==${TORCH_VERSION} --index-url ${TORCH_INDEX_URL} | ||
| case "${TARGETARCH}" in \ | ||
| amd64) torch_index="${TORCH_CUDA_INDEX_URL}" ;; \ | ||
| arm64) torch_index="${TORCH_CPU_INDEX_URL}" ;; \ | ||
| *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| esac && \ |
There was a problem hiding this comment.
Empty Target Architecture Fails Build
When this image is built with the documented plain docker build -f docker/pii.Dockerfile -t sim-pii . path and Docker does not inject BuildKit platform args, TARGETARCH is empty. The new case then takes the unsupported branch and the PII image build fails before installing torch, whereas the previous Dockerfile had a working CPU-wheel default.
| ARG TORCH_CUDA_INDEX_URL=https://download.pytorch.org/whl/cu128 | ||
| ARG TORCH_CPU_INDEX_URL=https://download.pytorch.org/whl/cpu |
There was a problem hiding this comment.
Torch Index Override Is Ignored
The old TORCH_INDEX_URL build arg was the documented control point for selecting the torch wheel index. After replacing it with TORCH_CUDA_INDEX_URL and TORCH_CPU_INDEX_URL, any existing build wrapper that still passes --build-arg TORCH_INDEX_URL=... silently downloads from the hard-coded upstream PyTorch index instead of the requested mirror or CPU-only index.
Greptile SummaryThis PR updates the PII image build and spreadsheet dependency handling. The main changes are:
Confidence Score: 4/5The torch build check should run after all Python dependencies are installed.
docker/pii.Dockerfile Important Files Changed
|
| case "${TARGETARCH}" in \ | ||
| amd64) torch_index="${TORCH_CUDA_INDEX_URL}" ;; \ | ||
| arm64) torch_index="${TORCH_CPU_INDEX_URL}" ;; \ | ||
| *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | ||
| esac && \ | ||
| pip install torch==${TORCH_VERSION} --index-url "${torch_index}" |
There was a problem hiding this comment.
Empty Target Architecture Fails
The selector now requires Docker to inject TARGETARCH, but the documented local build path for this image is plain docker build -f docker/pii.Dockerfile -t sim-pii .. On builders that do not provide automatic platform args, TARGETARCH is empty, so supported local amd64 builds hit the fallback arm and fail with unsupported TARGETARCH:.
| case "${TARGETARCH}" in \ | |
| amd64) torch_index="${TORCH_CUDA_INDEX_URL}" ;; \ | |
| arm64) torch_index="${TORCH_CPU_INDEX_URL}" ;; \ | |
| *) echo "unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \ | |
| esac && \ | |
| pip install torch==${TORCH_VERSION} --index-url "${torch_index}" | |
| arch="${TARGETARCH:-$(dpkg --print-architecture)}" && \ | |
| case "${arch}" in \ | |
| amd64) torch_index="${TORCH_CUDA_INDEX_URL}" ;; \ | |
| arm64) torch_index="${TORCH_CPU_INDEX_URL}" ;; \ | |
| *) echo "unsupported TARGETARCH: ${arch}" >&2; exit 1 ;; \ | |
| esac && \ | |
| pip install torch==${TORCH_VERSION} --index-url "${torch_index}" |
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
af1855f to
5030616
Compare
|
Thanks — went and checked both against the actual builder behavior. Neither reproduces, and here's the evidence. P1 — "Empty Target Architecture Fails Build" — not reachableThe premise is that Forcing the legacy builder fails on the first such RUN, long before the torch step: Any builder that can build this file is BuildKit, and BuildKit always populates So the One thing the suggestion would have missed even if the premise held: it only rewrites the P2 — "Torch Index Override Is Ignored" — no such wrapper exists
No CI job passed it (all three pii build jobs in Reintroducing it as a third override would add a second way to express the same thing, so I'd rather leave the two explicit Also force-pushed to drop an unrelated |
|
@greptile review |
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
Good catch — acted on this in d088912. First I checked whether it bites today. The only But the structural point stands: nothing pins torch in those later requirements files, so a future Confirmed Trade-off accepted: a wrong wheel index now fails later in the build instead of immediately. That only costs CI time, and correctness of the invariant is worth more than a fast failure. |
|
@greptile review |
Problem
The published
sim/piiimage installs a CPU-only torch build. On the ECS GPU fleet (g4dn.xlarge / NVIDIA T4), running withPII_ENGINE=gliner+PII_DEVICE=cudacrashes at model load:The GPU is genuinely attached — the nvidia container runtime injects it. The image's torch simply has no CUDA compiled in.
docker/pii.Dockerfilealready had anARG TORCH_INDEX_URLdefaulting to.../whl/cpu, with a comment saying the GPU variant just needs--build-arg. But no CI job ever passes a build arg, so every published image silently took the CPU default.Fix
Select the wheel index from Docker's built-in
TARGETARCH:cu128(GPU-capable; also runs on CPU)cpuA CUDA torch falls back to CPU when no GPU is present, so one image keeps serving both the Fargate CPU tasks and the EC2 GPU tasks from the same
sim/pii:stagingtag. Noci.ymlchange, no CDK change — rebuild and push, then re-enable the infra flag.Also adds a build-time assert so an amd64 image can never silently regress to a
+cpuwheel again — that failure currently only surfaces at GLiNER load time on a GPU host.Why cu128, and why arm64 is different
cu121was never viable. That index stops at torch 2.5.1; using it would downgrade the 2.11.0 pin by six minor versions.v2.11.0.ci/manywheel/build_cuda.sh, the12.8)case yields7.5;8.0;8.6;9.0;10.0;12.0—7.5is the T4.>=525.amzn2-ami-ecs-gpu-hvm-2.0.20260707-x86_64-ebsinstallsnvidia-driver-latest-dkms(>=535).build-ghcr-arm64job builds this same Dockerfile forlinux/arm64. A blanket CUDA default would break that job.cudnn,cublas,cuda_runtime, …); the host AMI supplies the driver. Base stayspython:3.12-slim-bookworm.Verification
Built the changed block for
linux/amd64and ran it:torch.version.cudais set (a CUDA build, not+cpu) andsm_75is present, which is the root cause addressed. CUDA runtime libs ship in the image (nvidia/{cublas,cudnn,cuda_runtime,nccl,...},libtorch_cuda.so~912 MB).linux/arm64build resolves to2.11.0+cpu/cuda=None, and the assert passes on both arches.Cost
torch wheel 181 MB → 782 MB, plus the
nvidia-*runtime packages: roughly +3-4 GB installed. The Fargate CPU tasks pull that too. Accepted in exchange for one image, one tag, and zero infra changes.Not verified here
The gated CPU-path suite (
RUN_PII_INTEGRATION=1 PII_DEVICE=cpu python -m pytest tests) needs a full ~13 GB image build, which is emulated on an arm64 dev box. Device plumbing is untouched (server.py:34maps unsetPII_DEVICEtoNone→ auto-detect → cpu), andtorch.cuda.is_available()isFalsewithout a GPU, so the CPU path behaves exactly as before.🤖 Generated with Claude Code
https://claude.ai/code/session_01QHNEWVrh7k89m8Wtqzhs18