Repository navigation
Description
Note
The technical body of this issue was drafted with an AI coding assistant and is
quoted verbatim below. I have reviewed it, independently reproduced the
measurements on my own Intel GPU system, and verified the code references
against the PyTorch tree. Filing it because it blocks device-agnostic TF32
handling in torch/testing/_internal/ test helpers: helpers whose entire
purpose is to guarantee full fp32 precision are silently no-ops on XPU today,
so the guarantee holds only by accident of the default value. Happy to move
this to pytorch/pytorch if that is the better venue -- see the note at the end
about where the affected files actually live.
AI-drafted content (reviewed and verified by me)
Summary
XPU TF32 is gated by a single private boolean, Context::allow_tf32_onednn, which
has no representation in the public fp32_precision API. As a result there is no
device-agnostic way to turn TF32 on or off for XPU. I would like XPU TF32 to be
reachable through the same public surface CUDA and MKLDNN already use.
Current state
The flag itself:
// aten/src/ATen/Context.h:512
bool allow_tf32_onednn = false;
// aten/src/ATen/Context.cpp:256
bool Context::allowTF32OneDNN() const {
return allow_tf32_onednn;
}It is the sole gate for both XPU matmul and XPU convolution:
// aten/src/ATen/native/mkldnn/xpu/detail/Matmul.cpp:200
if (m1_dt == dnnl::memory::data_type::f32) {
bool allow_tf32 = at::globalContext().allowTF32OneDNN();
if (allow_tf32) {
pattr.set_fpmath_mode(dnnl::fpmath_mode::tf32);
} else {
pattr.set_fpmath_mode(dnnl::fpmath_mode::strict);
}
}// aten/src/ATen/native/mkldnn/xpu/detail/Utils.cpp:582
void apply_tf32_if_allowed(dnnl::primitive_attr& pattr) {
auto& ctx = at::globalContext();
bool allow_tf32 = ctx.allowTF32OneDNN();
if (allow_tf32) {
pattr.set_fpmath_mode(dnnl::fpmath_mode::tf32);
}
}Meanwhile the structured precision registry has no XPU backend at all:
// aten/src/ATen/Context.h:48
enum class TORCH_API Float32Backend { GENERIC, CUDA, MKLDNN };
enum class TORCH_API Float32Op { ALL, CONV, RNN, MATMUL };So allow_tf32_onednn sits entirely outside the fp32_precision inheritance
chain (backend/op -> backend/ALL -> GENERIC/ALL).
The gap, measured
Measured on torch 2.13.0.dev20260525+xpu, torch.xpu.is_available() == True,
torch.xpu.is_tf32_supported() == True. None of the documented generic knobs
reach the XPU flag:
--- generic knob effect on XPU oneDNN tf32 bool ---
backends.fp32_precision='tf32' -> _get_onednn_allow_tf32() = False
backends.fp32_precision='ieee' -> _get_onednn_allow_tf32() = False
backends.fp32_precision='none' -> _get_onednn_allow_tf32() = False
--- legacy set_float32_matmul_precision effect on XPU ---
set_float32_matmul_precision('high' ) -> _get_onednn_allow_tf32() = False
set_float32_matmul_precision('highest') -> _get_onednn_allow_tf32() = False
set_float32_matmul_precision('medium' ) -> _get_onednn_allow_tf32() = False
--- per-op mkldnn precision does not drive XPU either ---
mkldnn.matmul.fp32_precision='tf32' -> _get_onednn_allow_tf32() = False
The only lever that works is the legacy oneDNN boolean:
initial : False
after backends.mkldnn.allow_tf32=True : True
after backends.mkldnn.allow_tf32=False : False
Also note torch.backends.xpu does not exist:
hasattr(torch.backends, "xpu"): False
Reproducer:
import torch
assert torch.xpu.is_available()
assert torch.xpu.is_tf32_supported()
for v in ("tf32", "ieee", "none"):
torch.backends.fp32_precision = v
print(v, torch._C._get_onednn_allow_tf32()) # always False
for v in ("high", "highest", "medium"):
torch.set_float32_matmul_precision(v)
print(v, torch._C._get_onednn_allow_tf32()) # always False
print(hasattr(torch.backends, "xpu")) # False
torch.backends.mkldnn.allow_tf32 = True # the only lever that works
print(torch._C._get_onednn_allow_tf32()) # TrueWhy this matters
1. Device-agnostic test infrastructure silently does nothing on XPU.
This is what prompted the request. torch/testing/_internal/ helpers such as
tf32_off() / with_tf32_off exist to guarantee full fp32 precision for tests
that use matmul or convolution incidentally. On XPU they are no-ops, because
every mechanism they could use is one of the ones measured above. A test wrapped
in with_tf32_off on XPU still runs with whatever the ambient TF32 state is. It
happens to pass today only because allow_tf32_onednn defaults to false -- the
guarantee is accidental, not enforced, and would break silently if the default
ever changed or if a preceding test set the flag.
2. allow_tf32 is the API being deprecated.
Routing XPU through torch.backends.mkldnn.allow_tf32 means depending on the
surface PyTorch is actively moving away from:
torch.backends.cuda.matmul.fp32_precision = "tf32"
(torch.backends.cuda.matmul.allow_tf32 = Trueis going to be deprecated)-- docs/source/notes/numerical_accuracy.md:118
3. The name is misleading. Controlling an Intel GPU feature via a knob
spelled mkldnn (a CPU backend) is confusing in user code and in test
infrastructure alike, and it conflates two unrelated backends: the CPU MKLDNN
(MKLDNN, MATMUL) registry entry and the XPU oneDNN boolean are different state
with the same apparent naming lineage.
4. No per-op granularity. One boolean covers both matmul and convolution, so
XPU cannot express the matmul-TF32-on / conv-TF32-off combinations that CUDA and
MKLDNN both support via separate MATMUL / CONV entries.
Proposal
Add XPU to the structured precision registry and expose it the same way the other
backends are exposed:
- Add
XPUtoFloat32Backend. - Register
(XPU, ALL),(XPU, MATMUL),(XPU, CONV)in thefp32_precision
map, defaulting toNONEso they inherit via the existing
backend/op -> backend/ALL -> GENERIC/ALLchain. - Back
allowTF32OneDNN()withfloat32Precision(Float32Backend::XPU, op),
treatingTF32as enabled andIEEEas disabled, so the oneDNN call sites in
Matmul.cpp/Utils.cppneed minimal change. - Expose
torch.backends.xpu.matmul.fp32_precisionand
torch.backends.xpu.conv.fp32_precisionin Python, mirroring
torch.backends.cuda/torch.backends.mkldnn. - Keep
torch.backends.mkldnn.allow_tf32working as a deprecated alias.
The desired end state is that torch.backends.fp32_precision = "ieee" disables
TF32 on XPU exactly as it does on CUDA, so one device-agnostic code path is
correct for both.
Impact
Positive:
- Device-agnostic TF32 helpers become correct on XPU; test infrastructure in
torch/testing/_internal/can cover XPU without an XPU-specific branch. - XPU aligns with the non-deprecated
fp32_precisionAPI. - Per-op (matmul vs conv) control becomes possible on XPU.
- XPU precision state becomes visible to the
TestCasefp32-precision leak
detector, which currently tracks sixfp32_precisionflags and cannot see
allow_tf32_onednn.
Risk / compatibility:
- Behavior change risk is low if
(XPU, *)defaults preserve the current
allow_tf32_onednn = falsedefault. Worth confirming thatNONEinheriting
from an unsetGENERIC/ALLresolves to TF32-off for XPU, so no existing
workload silently gains TF32. Float32Precision::BF16is rejected for CUDA; the XPU policy forbf16needs a
decision.- Adding a
Float32Backendenumerator touches aTORCH_APIenum -- ABI-relevant,
so it likely wants to land with a PyTorch-side change rather than standalone.
One routing note from me: the affected files (aten/src/ATen/Context.*,
aten/src/ATen/native/mkldnn/xpu/) all live in the pytorch/pytorch tree rather
than in this repo -- as the README notes, XPU conv and gemm are implemented
directly in PyTorch sources. I am filing here for visibility and routing; glad to
refile upstream if maintainers prefer.
Environment: torch 2.13.0.dev20260525+xpu, Intel GPU with
has_subgroup_matrix_multiply_accumulate == True.
Activity
CuiYifeng commentedon Sep 2, 2026
Depends on
torch.backends.xpuCuiYifeng commentedon Oct 23, 2026
Please be aware of #2400.
daisyden commentedon Nov 10, 2026
label-issue: #4919
Root cause:
Float32Backendhas no XPU entry (aten/src/ATen/Context.h:52); XPU TF32 is the private boolallowTF32OneDNN()(Context.cpp:301) read by mkldnn/xpu/detail/Matmul.cpp:202 and Utils.cpp:587, so fp32_precision knobs never reach it.
typeFeatureissue_typeisFeature(human-set).testtest: utmodulemodule: corepriorityLowdtypedtype: float32Applied to this issue. Generated by a local
label-issuerun.