Skip to content

Add Intel GPUs (XPU) inference support - #423

Open
rajeshgangireddy wants to merge 15 commits into
Biohub:mainfrom
rajeshgangireddy:xpu-support
Open

rajeshgangireddy wants to merge 15 commits into
Biohub:mainfrom
rajeshgangireddy:xpu-support

Conversation

@rajeshgangireddy

@rajeshgangireddy rajeshgangireddy commented Oct 8, 2026 •

Copy link
Copy Markdown

Summary

Adds Intel XPU inference for ESMC, ESMFold2, and ESM3. Pass device="xpu"; CPU
and CUDA paths remain available.

  • Route device selection, autocast, RNG state, and memory helpers by device.
  • Enable supported ESMFold2 Triton kernels on XPU and add an inference-only
    fp32 ESMC RoPE kernel. CUDA-only libraries use reference paths by default;
    explicitly selecting cuequivariance on XPU raises an error.
  • Add Pixi XPU environments for Python 3.12–3.14, focused tests, and a README
    usage note.

Validation

Compared published checkpoints on the same machine, using an RTX 3090
(CUDA) and Intel Arc Pro B70 (XPU). Each device was run separately with the
same inputs and precision; the results were then compared.

Checkpoint CUDA vs XPU
ESMC-300M, fp32 100% token argmax agreement across ubiquitin, GB1, and lysozyme; max logit difference 1.5e-4
ESMFold2-Experimental, bf16 Mean aligned Cα-RMSD 0.30 Å (ubiquitin) and 0.14 Å (GB1) across eight paired diffusion samples
ESM3 sm-open-v1, bf16 100% masked-token argmax agreement; generated-structure aligned Cα-RMSD 0.32 Å (ubiquitin) and 0.27 Å (lysozyme)

Diffusion and iterative generation are not bit-identical across devices.
ESMFold2 structures from both devices were also close to the experimental
structures: 1.03 Å to 1UBQ and 0.40–0.45 Å to 1PGA.

The default, CUDA, and XPU test runs completed without unexpected failures:
418, 32, and 23 tests passed, respectively.

On the B70, the ESMC RoPE kernel reduced warmed fp32 forward latency by
23% for a short sequence and 5% for a longer batch. Compiling from an
empty Triton cache adds about 4.9 seconds to the first call.

Scope

Multi-XPU inference is not included. The full ESMFold2 checkpoint was not
compared against CUDA because its fp32 backbone exceeds the 3090's 24 GB;
the Experimental checkpoint was used instead.

While working on this PR, I saw that support for MPS was also created (#409). Quite some changes follow similar pattern. Would rebase if that get's merged first.
Let me know if any further numbers/validation needs to be done.

torch/triton-xpu from the pytorch xpu wheel index, own solve-groups
so they don't affect the existing cuda/cpu environments.
resolve_default_device/autocast_device_type/empty_cache/synchronize/
manual_seed_all/*_rng_state_all dispatch to cuda or xpu. Extends
fp32_autocast_context with an xpu branch alongside its existing
cpu/cuda/mps ones.
esm3.py, esmc/model.py, esmc/compatibility.py, widgets/utils/clients.py
now resolve their default device via esm.utils.device instead of
'cuda' if torch.cuda.is_available() else 'cpu'. Autocast-enable
conditions gated on device.type == 'cuda' now use
supports_amp_autocast so xpu gets the same bf16 autocast cuda does.
torch.amp.autocast("cuda", ...) call sites now derive device_type
from the actual tensor/device instead of a literal 'cuda', so xpu
gets the same bf16 autocast path cuda does. The precision-guard
@autocast("cuda", enabled=False) decorators (Kabsch alignment, RMSD)
get a paired @autocast("xpu", enabled=False) so they disable autocast
on whichever device is actually active.
processor.py's _seed_context saved/restored torch.cuda's rng state
directly; now goes through esm.utils.device so xpu is covered too.
- generalize the two remaining hardcoded cuda autocast sites
- _seed_context saves/restores rng state via esm.utils.device
- allow the vendored Triton kernels to import on xpu, not just cuda
  (is_cuda checks -> device.type in (cuda, xpu))
- CUE_AVAILABLE now also requires torch.cuda.is_available(): the
  cuequivariance import can succeed on xpu even though the library
  JIT-compiles via nvrtc and can't actually run there
- FusedLNLinearSwiGLUFunction's forward/backward used
  torch.amp.custom_fwd/custom_bwd(device_type="cuda"), which silently
  skips the bf16 cast under an xpu autocast context since device_type
  is fixed at decoration time. Replaced with an explicit, device-derived
  equivalent. Verified forward+backward on both cuda and xpu: bf16
  autocast now engages correctly and both devices land on the same
  max-diff vs an fp32 reference.
Rename only; this flag gates CUDA-only libs (flash-attn, TE), not
whether an accelerator is present at all.
- xpu pytest marker
- esmc_test: cpu-vs-xpu agreement + build matrix
- esmfold2_test: kernel_backends_agree extended to xpu/fused
- esmfold2_builds_test: cpu-vs-xpu agreement, use_amp, build matrix
- fixed stale use_amp docstring (now supports_amp_autocast, not a cuda string check)

All tolerances measured on real hardware (RTX 3090 / Arc Pro B70), not guessed.
@rajeshgangireddy
rajeshgangireddy marked this pull request as ready for review October 8, 2026 15:27
@rajeshgangireddy rajeshgangireddy changed the title Add Intel XPU inference support for ESMC, ESMFold2, and ESM3 Add Intel GPUs (XPU) inference support Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant