If your team trains or fine-tunes PyTorch models and you avoided TPUs because torch_xla meant lazy tensors, graph recompiles, and painful debugging, there is now a second path worth a pilot: TorchTPU, a native PyTorch backend for Google TPUs that runs unmodified eager code after a device-string swap. If you are already running Hugging Face models on TPUs through Optimum TPU, the question is not whether to evaluate TorchTPU but when, because Hugging Face states that Optimum TPU “is not required anymore to run Hugging Face models with Transformers and Diffusers” now that native support exists.
The practical answer, up front: existing Optimum TPU users should plan the migration now. Everyone else should run a bounded eager-mode pilot against their own model, check it against the published test coverage, and treat every performance number currently in circulation as vendor-reported rather than as a benchmark. What follows is the porting surface, the execution modes in order of risk, and the decision frame that separates what the sources establish from what they do not.
What changed in October 2026
At PyTorch Conference 2026, Google announced that TorchTPU, its native PyTorch stack for TPUs co-developed with Meta’s PyTorch team, is now open source on GitHub. The project was initiated at Google in mid-2025, per the TorchTPU paper. In parallel, Hugging Face shipped native TPU support in Transformers v5 and Diffusers, making the Optimum TPU path unnecessary for those libraries.
Google’s framing is expansive: “With TorchTPU, TPUs join GPUs and CPUs as a native option for PyTorch.” The ecosystem roster the announcement names includes vLLM, SGLang, llm-d, TorchTitan, Ray, TorchRec, and Hugging Face. That roster is a vendor claim about integration breadth, not evidence that any specific serving or training stack works well on your workload, but it does indicate where Google is concentrating support.
One caution on timing: “Optimum TPU is not required anymore” is Hugging Face’s framing of its own integration, not a formal sunset timeline covering everything Optimum TPU ever did. If your usage extends beyond Transformers and Diffusers, the urgency of migrating is less established by these sources.
What torch_xla actually cost you
The architectural case for TorchTPU rests on a critique of its predecessor, and the TorchTPU paper states it directly: “PyTorch/XLA required intrusive source-code modifications to explicitly define compilable regions, suffered from severe compile-time latency, lacked support for PyTorch’s native imperative (‘eager’) execution mode, and lagged in supporting emerging distributed computing primitives within the PyTorch ecosystem.”
Translated into operational terms: under torch_xla, tensors were lazy, so your code built a graph that only executed when forced, which made debugging an exercise in reasoning about deferred state you could not inspect normally, and which meant that shape changes or control flow could trigger expensive recompiles mid-run. TorchTPU’s stated design principles invert this. According to the paper: “TorchTPU was built as a principled TPU backend for PyTorch: eager execution is a top priority, and existing PyTorch workloads run out of the box with trivial code changes (e.g., .to(“cuda”) → .to(“tpu”)).” Other listed principles include no JAX dependencies in the runtime, a Dynamo-based torch.compile path, TPU collectives exposed at the PyTorch ProcessGroup API level, and bounded dynamism to avoid shape-driven XLA recompilation.
Whether eager mode on TPU actually delivers competitive throughput for your model is a separate question from whether it runs, and the sources do not settle it independently. Keep those two questions separate when you evaluate.
The porting surface
The mechanics are genuinely small. Per the TorchTPU documentation: “Porting a workload from a GPU to a TPU starts with changing device=“cuda” to device=“tpu” and backend=“nccl” to backend=“tpu_dist”. Your unmodified PyTorch model runs immediately in eager mode, with clear error messages when diagnosing runtime or compiler issues.” TorchTPU also replaces the PrivateUse1 device name with “tpu” on wheel autoload, so PyTorch code that branches on device type sees a first-class device string.
For the Hugging Face stack specifically, the Hugging Face announcement documents the integration points: in Transformers v5, loading on TPU is device_map="tpu"; Diffusers supports eager mode via pipe.to("tpu") and compiled mode via pipe.transformer.compile(backend="tpu", fullgraph=True, dynamic=False).
“Minimal code changes” covers device placement and the distributed backend string. It does not cover custom CUDA kernels, which have no TPU equivalent and must be rewritten, nor does it guarantee numerical parity with your GPU baseline, which you still have to measure.
Execution modes, in order of risk
The sane adoption sequence is eager first, compile later, kernels last.
Eager mode is the default and the design’s stated top priority. It is also the lowest-risk validation surface: your code runs line by line, errors surface at the operation that caused them, and you can diff outputs against a CPU or GPU run directly.
Deferred-fusion eager is an intermediate mode documented in the openlm.ai documentation, which also describes a compilation cache design to amortize compile costs across runs.
torch.compile with backend=“tpu” is where the speed claims live, and where the architecture gets opinionated. TorchTPU registers a TorchDynamo backend that compiles the whole FX graph to a single StableHLO program. Notably, per the documentation: “TorchTPU does not use TorchInductor, instead reusing the mature XLA compiler stack that has developed alongside the TPU architecture.” That choice matters operationally: compilation still exists, first compiled calls are still slow, and the XLA heritage means shape stability still influences performance even though bounded dynamism reduces shape-driven recompilation. Hugging Face’s own Diffusers example took 188 s compiled versus 262 s eager on one pipeline, per the Hugging Face post, meaning compilation paid off only after its upfront cost; the exact speedup is author-reported.
The inference I would draw, and it is inference rather than a sourced claim: profile in eager, find the hot regions, and only then spend compile budget where the graph is static enough to benefit. That sequence follows from the documented architecture, not from any source’s explicit recommendation.
Custom ops: Pallas, Helion, and the Kernels Hub
If your model uses custom CUDA kernels, this is where porting stops being a string swap. TorchTPU’s answer is Pallas, with Helion as a kernel-authoring option, and prebuilt kernels distributed through the Kernels Hub, including Tokamax kernels, per the Hugging Face post and the official docs, which list custom kernel support, dynamic shapes, FSDP usage, XProf profiling, and numerical precision controls as documented areas. The paper labels Pallas kernel authoring and Tokamax kernels production ready and Helion experimental, so a Helion rewrite is the least settled of the three routes.
The headline kernel result is author-reported and worth labeling as such: Hugging Face reports a Tokamax ragged-dot Pallas kernel delivering 21.5× faster batch-64 decoding on Qwen3-30B-A3B and 12.8× on Gemma 4 26B-A4B versus the default implementation on TPU v6e-8. That is a comparison against TorchTPU’s own default path on one hardware configuration, not against a tuned GPU baseline. It shows the Kernels Hub can matter a lot for MoE decode; it does not show TPUs beat GPUs for MoE decode.
For an arbitrary custom op, the sources do not establish that Pallas coverage will suffice. Treat kernel porting as scoped engineering work with its own schedule, not as a checkbox in the migration.
Distributed training and what the largest validation shows
TorchTPU implements TPU collectives at the PyTorch ProcessGroup API level, supporting DDP, FSDP, and DTensor idioms, per the paper, with backend="tpu_dist" replacing NCCL. Google reports that “TorchTitan provides recipes for pre-training large dense models (such as Llama 3 70B/405B, Qwen 3 8B/32B, and MuseGlimmer 30B), Mixture-of-Experts (MoE) such as Qwen 3 235B, and diffusion transformers (such as FLUX.1 12B), and has been validated running with up to 8000 Ironwood TPUs (TPU v7x).” That is vendor-reported.
The 8,000-chip validation validates the named TorchTitan recipes at that scale on that hardware. It does not prove your FSDP configuration, your parallelism layout, or your data pipeline will scale similarly. This is where the strongest independent evidence among these sources cuts against optimism: an academic study of AlphaFold2 on cloud TPUs concluded that “realized performance on TPU depends on how parallelism is expressed rather than on the accelerator alone.” A native backend removes the framework friction of expressing parallelism in PyTorch idioms; it does not remove the workload-specific problem of expressing it well.
Coverage and maturity: check your model before you port
The most useful maturity signal is the CI corpus. The paper states: “We continuously evaluate about 5,000 Hugging Face models across hundreds of architectures in both eager and compiled modes on TPU hardware generations starting from v5e.” On the parity metric reported in the paper, 638 of 657 models matched GPU behavior, a 97% figure that is author-reported. For bounded dynamism with symbolic shapes, the paper reports correct numerics on 834 of 839 causal LLMs evaluated (99%).
The Hugging Face announcement is more candid about its own numbers: “Of the tests that run on TPU, 96.5% pass. Every failure we find becomes a small repro script and an issue on the TorchTPU repo. So far we have reported 34 issues, and 19 are already fixed. Running on TPU also caught a few bugs in Transformers itself, like in StaticCache and the Qwen3 tensor-parallel plans. We fixed those upstream.”
Two things follow. First, the residual failure set is real: roughly 3.5% of Hugging Face’s TPU tests and about 3% of the paper’s parity checks fail, and neither source characterizes which architectures those failures concentrate in. Check the CI coverage and the TorchTPU issue tracker for your specific model family before assuming a clean port. Second, the failure-to-issue-to-fix pipeline is functioning publicly, which is the right kind of immaturity for a new backend. These counts will drift quickly; recheck them against the repo at the time you act.
The decision frame
| Your situation | Recommendation | Why |
|---|---|---|
| Existing Optimum TPU / HF-on-TPU user | Migrate on your next maintenance window | HF says Optimum TPU is not required anymore; TorchTPU is the replacement path for Transformers/Diffusers |
| PyTorch-first team curious about TPU economics | Pilot in eager mode first | Porting friction is a device and backend swap; validate against the 5,000-model CI corpus before investing |
| Training large models with FSDP/DTensor | Pilot against TorchTitan recipes, then your own config | 8,000-chip validation is vendor-reported and recipe-specific |
| Models with custom CUDA kernels | Scope a Pallas/Helion rewrite separately | Kernel porting is engineering work, not a string swap |
| Fleet purchase or large committed-use decision | Wait for your own measurements | The one independent comparison among the sources cited here, SemiAnalysis InferenceX, is cited secondhand by the paper and covers inference serving only; no independent training or torch_xla comparison appears in the available evidence |
Most performance figures in this article come from Google, Meta, or Hugging Face: the 21.5× decode and 96.5% test-pass numbers from Hugging Face, the 59% MFU figure on a Muse Glimmer 30B implementation and the 97% parity result from the paper, and the 8,000-chip validation from Google. The exception that matters for economics is price-performance: the paper cites an independent benchmark published by SemiAnalysis (InferenceX), in which Google’s TPU v7 paired with the vLLM-TorchTPU stack delivered “industry-competitive performance-per-dollar,” including “lowest cost per million tokens overall at 2.01 cents” on the InferenceX 8K/1K workload. That is the only independent comparison referenced in the available sources, and it arrives secondhand: the SemiAnalysis report itself is not among these sources, and its results cover inference serving, not training. There is still no independent TorchTPU-versus-torch_xla measurement and no independent training-side comparison in the available evidence, so the fleet economics question cannot be settled from them. The AlphaFold2 finding reinforces this: accelerator-level numbers do not transfer to a workload without validating how that workload’s parallelism is expressed.
My judgment: if you are on Optimum TPU for Transformers or Diffusers, migrate now, because Hugging Face has made native TPU support the documented path and states that Optimum TPU is not required anymore for those libraries. If you are PyTorch-first and TPU-curious, the pilot is cheap enough to run this quarter, and eager mode makes it debuggable in a way torch_xla pilots never were. But run the pilot as a measurement exercise against your GPU baseline, not as a confirmation exercise for the launch numbers. The backend removes the reason many teams refused to look at TPUs. Whether TPUs win on your workload is still yours to measure.
Frequently Asked Questions
What code changes are required to port a PyTorch workload from GPU to TPU using TorchTPU?
Porting a workload from a GPU to a TPU starts with changing device=“cuda” to device=“tpu” and backend=“nccl” to backend=“tpu_dist”. Your unmodified PyTorch model runs immediately in eager mode, with clear error messages when diagnosing runtime or compiler issues.
How does TorchTPU handle custom CUDA kernels that do not have a direct TPU equivalent?
TorchTPU’s answer is Pallas, with Helion as a kernel-authoring option, and prebuilt kernels distributed through the Kernels Hub, including Tokamax kernels, per the Hugging Face post and the official docs, which list custom kernel support, dynamic shapes, FSDP usage, XProf profiling, and numerical precision controls as documented areas.
What is the recommended adoption sequence for execution modes when migrating to TorchTPU?
The sane adoption sequence is eager first, compile later, kernels last.

Join the discussion
Share a useful perspective or ask a question about this article.