Repository navigation
Description
XPU alignment triage
The daily XPU alignment workflow posts audit summaries and independently reviewed candidates here.
Every run for which the deterministic gate produces a decision posts one Run Summary, separate from any candidate draft:
XPU alignment run complete: collection and review completed without terminal warnings.XPU alignment run completed with warnings: one or more units were isolated, while the remaining reviewed results are still valid and the workflow stays green.XPU alignment run completed with partial collection: fetching stopped before every source completed; source progress and the terminal error are reported, trusted candidates may still be published or queued, and the workflow finishes red.XPU alignment run failed: a malformed artifact, coverage gap, required producer failure, or other global blocker prevents all candidate publication and the workflow finishes red.
A Run Summary is a snapshot of the completed workflow attempt; each candidate draft comment carries the current filing state.
Only terminal conditions that affect the final outcome are shown in the Run Summary. Recovered retries, transient API failures, and internal tool errors remain in workflow logs and artifacts. A scheduled retry updates the existing Summary for the same run ID; duplicate scheduled Summary markers fail closed. Dry runs may post repeated summaries. If the publisher itself or the GitHub Issues API fails, the Actions result and gate artifact are the fallback because a comment cannot be guaranteed.
Formal scheduled drafts may be approved one at a time with:
@torchxpubot file <unit-id>
- Run the command on this issue only.
- Only repository
OWNERorMEMBERaccounts may approve filing. - A formal reviewed draft from either a complete scheduled scan or a structurally valid partial scheduled scan can be filed.
- A scheduled run with exactly one reviewed payload may file it automatically, including when collection is structurally valid but partial.
- Partial runs report source progress, last cursor, rate-limit reset, and terminal errors, notify maintainers, and finish red even when trusted candidates were published or queued.
[DRY RUN]drafts are test output, may repeat, never notify, and cannot be filed.- Malformed artifacts, incomplete stage coverage, core environment failure, or a failed producer job produce only a failed Run Summary and no formal draft.
- A runner-backed blocker for one unit excludes that unit without invalidating other fully reviewed candidates.
- Historical diagnostic comments remain historical evidence and cannot be filed because they do not carry a formal unit marker.
- The bot copies the reviewed formal draft into a new
[xpu-alignment]issue with exactly theai_generatedlabel. - A formal unit can be filed successfully only once; the draft is marked with the created issue number.
- No agent runs between approval and issue creation.
- Before approving, check the scan date, workflow run, reproducer, XPU result, independent reviewer verdict, and any incomplete-collection summary.
Activity
github-actions commentedon Aug 26, 2026
alignment scan
2026-08-24, run32923438489[DRY RUN] [xpu-alignment] embedding_bag per_sample_weights backward indexes weight/grad with unchecked, int-truncated saved indices on XPU
Summary
aten::_embedding_bag_per_sample_weights_backwardon XPU indexesgradandweightwith the savedindices/offset2bagvalues without any bounds check, and truncates both toint. Upstream fixed the equivalent CUDA kernel in the 2026-08-24 window; that fix cannot reach this repository, and its regression tests are CUDA-only.Upstream source
The upstream change to
aten/src/ATen/native/cuda/EmbeddingBag.cudoes two things. It stops truncatingoffset2bag[i]andindices[i]with(int)and keeps both atindex_t, and it addsCUDA_KERNEL_ASSERTguards for0 <= bag_idx < num_bagsand0 <= embedding_idx < num_embeddingsbefore those values are used to addressgradandweight. Both regression tests it adds totest/nn/test_embedding.py--test_embedding_bag_per_sample_weights_rejects_invalid_saved_indicesandtest_embedding_bag_per_sample_weights_large_index-- are decorated@onlyOn(["cuda"]), so nothing exercises XPU.Target-path evidence
This op is implemented in this repository, so no upstream change reaches it. Line numbers are from
intel/torch-xpu-opsmain:src/ATen/native/xpu/sycl/EmbeddingBag.cpp:912--_embedding_bag_per_sample_weights_backward_kernelsrc/ATen/native/xpu/sycl/EmbeddingBag.cpp:722--_embedding_bag_per_sample_weights_backward_impl(called at:952)src/ATen/native/xpu/sycl/EmbeddingBag.h:219--EmbeddingBagPerSampleWeightsBackwardKernelFunctorThe functor body is the exact pre-fix CUDA code:
Neither
num_bagsnornum_embeddingsis passed into the functor, so no bound is even available to check against. The XPU forward kernel does guard its index --SYCL_KERNEL_ASSERT(weight_index < num_row_)atsrc/ATen/native/xpu/sycl/EmbeddingBag.h:104, upper bound only -- which makes the missing backward guard an internal inconsistency as well as a CUDA divergence.The
(int)casts are a second, independent defect: an int64 index at or above 2^31 wraps and addresses the wrong row even when the index is perfectly valid. That is what upstream'stest_embedding_bag_per_sample_weights_large_indexcovers, also CUDA-only.Observed XPU behavior
Backward with an out-of-range saved
indicesvalue completes silently.weighthas 5 rows, every saved index is set to 5 (== num_embeddings), and the per-sample-weights gradient is computed from aweightread one row past the allocation. Upstream's post-fix contract is that such an index is rejected by a device-side assertion.Reproducer
The child runs out of process because the expected upstream outcome is a device-side abort that cannot be caught in process, and it calls
torch.xpu.synchronize()before printing so an asynchronous device fault would surface before exit.Observed output
No
ALIAS_FALLBACKline appears, so the DLPack alias -- not.data-- mutated the saved tensor and autograd's version counter was not bumped: the value the kernel read really was the saved one.Scope of the evidence
Only the
indicesupper-bound int64 case executed; the harness stops at its first failure. Theoffset2bagcase, the negative-bound cases and the int32 cases in upstream's parametrization were not run. Their status here comes from source inspection:bag_idxis equally unguarded, and no lower bound is checked for either index.One qualification on the signal. A clean exit demonstrates that the invalid index was used unguarded, not that memory outside the USM allocation was touched -- a two-element overread past a 5x2 fp32 buffer will usually stay inside the same page, so a clean run is expected even though the access is out of bounds. The defect is established by the source above; the run corroborates that no assertion exists.
Suggested fix
Mirror the upstream change:
grad.size(0)(num_bags) andweight.size(0)(num_embeddings) from_embedding_bag_per_sample_weights_backward_implinto the functor.offset2bag_[i]andindices_[i]atindex_tinstead of casting toint, and keep the addressing arithmetic at that width.SYCL_KERNEL_ASSERTbounds checks for both indices before thegrad_/weight_reads.Environment
/opt/conda/bin/python3.13, invoked with-I./opt/conda/lib/python3.13/site-packages/torch, built from/__w/pytorch/pytorch.torch.xpu.is_available(): true, asserted by the script before the case ran.Provenance
Produced by the
xpu-alignmentskill in automation mode, and reviewed independently of the scan that produced the local result. Reproduceralignment-run/scripts/repro_commit-550fa843275302768fc1fe758f308b2dccf543b2.py(sha2566af1ae19088e7db7c2f8b19ef68c2dfb6771e524b41509a471665725c9431bc6), logalignment-run/runner/logs/commit-550fa843275302768fc1fe758f308b2dccf543b2.log.github-actions commentedon Aug 26, 2026
alignment scan
2026-08-24, run32923438489[DRY RUN] [xpu-alignment] XPU group_norm rejects fp32 affine params over an fp16 input, which the shared ATen mixed-dtype contract supports
Summary
XPU
group_normraisesRuntimeError: expected scalar type Half but found Floatfor a reduced-precision input with fp32 affine parameters -- a combination the shared ATen layer explicitly validates and allocates buffers for, and that CPU computes. Root cause: both XPU dispatch stubs template the entire implementation onX.scalar_type(), so the fp32 buffers the shared layer allocated are accessed as the input type.Upstream source
Among other changes, that PR threads a separate parameter type through the CUDA group norm kernels and allocates
dgamma/dbetafromparam_scalar_type(X, mixed_type)in sharedaten/src/ATen/native/group_norm.cpp. Validating its mixed-dtype contract on XPU surfaced a different, pre-existing failure: XPU does not accept the mixed-dtype call at all.Why this is a defect and not unsupported input
Shared
aten/src/ATen/native/group_norm.cppsupports the combination explicitly:For an fp16
Xwith fp32gamma/beta, the shared layer validates the combination and allocatesmean/rstdas fp32 before calling the backend stub.This is also the ordinary AMP shape rather than an exotic input:
group_normhas no autocast cast policy outside MPS --KERNEL_MPS(group_norm, fp32)is the only entry inaten/src/ATen/autocast_mode.cpp-- so undertorch.autocast("xpu")aGroupNormfed by a preceding fp16 op receives an fp16 activation together with its own fp32 parameters, unchanged.Root cause and target-path evidence
Line numbers are from
intel/torch-xpu-opsmain,src/ATen/native/xpu/sycl/GroupNormKernels.cpp::1379--group_norm_kernel:AT_DISPATCH_FLOATING_TYPES_AND2(kHalf, kBFloat16, X.scalar_type(), ...):2445--group_norm_backward_kernel: the same, onX.scalar_type()alone:1042--mean.mutable_data_ptr<T>(), the first throw site (meanis fp32 when mixed,Tis bound toHalf):1055,:1717,:2273--gamma.const_data_ptr<T>():1777,:2401--dgamma.mutable_data_ptr<T>()Because
Tis bound to the input's scalar type for the whole implementation,mutable_data_ptr<Half>()on the fp32meanthrows, which is exactly the observed message. There is no separate parameter type anywhere in the file.The target path is established rather than assumed: the reproducer asserts the XPU dispatch key for both
aten::native_group_normandaten::native_group_norm_backwardbefore any call, and every tensor is allocated onxpu.Reproducer
The same dispatch path is reached from the user-facing module form below. This form was not executed in the run that produced the output quoted next; it is derived from source (
nn.GroupNorm.forward->F.group_norm->at::group_norm->native_group_norm) and is included because it is how the failure is likely to be met in practice:Observed output
The
cpureference run happens immediately before thexpurun and outside thetry, and it succeeded -- so the identical Python-level call computes on CPU and raises on XPU.Relationship to CUDA and to PR #194616
Stated plainly so this is not mistaken for an XPU-only regression: CUDA on
mainhas the same single-type templating (aten/src/ATen/native/cuda/group_norm_kernel.cu:844mean.mutable_data_ptr<T>(),:899and:962gamma.const_data_ptr<T>()), so both GPU backends reject this call today. The divergence is from CPU, which computes it, and from the shared layer's own stated contract.It still needs work here: PR #194616 fixes the CUDA half and touches no XPU file, so no upstream change can reach
GroupNormKernels.cpp. #194616 is the reference design to mirror.No upstream test would catch this on XPU either.
test_groupnorm_nhwcis@onlyCPU;test_groupnorm_nhwc_cudaandtest_groupnorm_unaligned_inputare@onlyCUDAand convert the whole module to a single dtype;_test_GroupNorm_cpu_mixed_dtyperuns only whendevice == "cpu".Scope of the evidence
affinecase ran. Thegamma-undefinedcase -- undefinedgammawith an fp32beta, where upstream'sdgamma/dbetaallocation change matters -- never executed, because the harness stops at the first failure.group_norm_memory_formatreturnssuggest_memory_format()only for CPU, CUDA and PrivateUse1, so channels_last is not part of XPU's group norm contract today and asserting it would not be a faithful oracle.D == 1is a throughput change and needs a performance harness; nothing here speaks to it.Suggested fix
Introduce a separate parameter type in
GroupNormKernels.cpp: useparam_scalar_type(X, mixed_type)for themean/rstd/gamma/beta/dgamma/dbetaaccesses while keepingTfor the activation reads and writes, and dispatch on both types, as upstream does for CUDA in #194616. Then add an XPU mixed-dtype test covering theaffineandgamma-undefinedcases for fp16 and bf16 inputs, since the existing upstream mixed-dtype test is CPU-gated.Environment
/opt/conda/bin/python3.13, invoked with-I./opt/conda/lib/python3.13/site-packages/torch, built from/__w/pytorch/pytorch.torch.xpu.is_available(): true, asserted before the dispatch-key probes.Provenance
Produced by the
xpu-alignmentskill in automation mode, and reviewed independently of the scan that produced the local result. Reproduceralignment-run/scripts/repro_pr-194616.py(sha256f694e48f6f691c871d0bb11d89234ec15b94a0f22da283f8931c11251f28fc07), logalignment-run/runner/logs/pr-194616.log.github-actions commentedon Aug 26, 2026
[DRY RUN] XPU alignment run
Dry run completed with
triageand 2 review-approved candidate(s).commit-550fa843275302768fc1fe758f308b2dccf543b2— [xpu-alignment] embedding_bag per_sample_weights backward indexes weight/grad with unchecked, int-truncated saved indices on XPUpr-194616— [xpu-alignment] XPU group_norm rejects fp32 affine params over an fp16 input, which the shared ATen mixed-dtype contract supportsThis run did not finish cleanly:
scan-blocked-result:commit-2509857d0e811629f1d34c3d187c172a7c8bc935:blocked-platform,scan-blocked-result:commit-e812f6fc74ce93d55284ca7534d84c7356c4ea94:blocked-envReviewed candidates were published or queued; blocked units were excluded.
alignment scan
2026-08-24, run32923438489github-actions commentedon Aug 27, 2026
github-actions commentedon Aug 27, 2026
[Workflow] Add the daily XPU alignment scan, review and filing pipeli…
[Workflow] Add the daily XPU alignment scan, review and filing pipeli…
github-actions commentedon Aug 29, 2026
alignment scan
2026-08-28, run33228378520[xpu-alignment] embedding_renorm_ derives the row width from stride(0) and faults on a zero-width embedding
Upstream source
[CUDA] illegal memory read on renorm_kernel(OPEN, created 2026-08-28).aten/src/ATen/native/cuda/Embedding.cuonly, and its regression test is@onlyOn(["cuda"]).[2026-08-28T00:00:00Z, 2026-08-29T00:00:00Z).Observed XPU behavior
F.embedding(indices, weight, max_norm=1.0, norm_type=2.0)with a zero-widthweight fails on XPU:
CPU, given the identical inputs, returns shape
(1, 0)cleanly. The oracle hereis CPU plus the upstream signature, not a tolerance comparison.
Root cause and target-path evidence
src/ATen/native/xpu/sycl/Embedding.cpp:237takes the same shortcut upstreamnames as the CUDA root cause:
torch.empty(20, 0).stride()is(1, 1), sodimbecomes1while the realrow width
self.size(1)is0.dimis passed toembedding_renorm_template, andRenormKernelFunctor::operator()(
src/ATen/native/xpu/sycl/Embedding.cpp:100-141) then runs its accumulationloop once and dereferences
weights_[base_index]:The
(20, 0)weight has zero elements, so that pointer has no backingallocation - the same invalid read compute-sanitizer reports for CUDA. The fix
is the same one-line change: use
self.size(1). The kernel already receivesweights_stride0/weights_stride1separately for indexing, so it does notdepend on the tensor being contiguous, and
dim == 0makes both loops executezero times without skipping the launch.
Target-path proof that this is the XPU kernel and not setup data or an
unsupported input:
xpu:0and in exactly thestride(0)=1, size(1)=0state the defect requires;an input-validation rejection;
embedding_renorm_is dispatched to XPU viaembedding_renorm_xpu_insrc/ATen/native/xpu/Embedding.cpp:39, so no fallback is involved;XPU work on the same device in the same run, so this is a kernel-level fault
rather than a global environment failure.
The UR error code alone does not distinguish an out-of-bounds device read from a
degenerate launch derived from
dim; both trace to the same line, and eitherway the oracle is violated on the XPU path.
Reproducer
Environment
torch 2.15.0.dev20260826+xpu, Python 3.13.13 (/opt/conda/bin/python3.13),Intel(R) Arc(TM) Pro B60 Graphics,torch.xpu.is_available() == True, noenvironment warnings. Neither upstream fix candidate is present in this build.
Ownership
The kernel is torch-xpu-ops code.
pytorch/pytorch#195208fixes only the CUDAkernel and adds a CUDA-only test, so nothing upstream will fix or detect the XPU
copy. No
pytorch/pytorchissue or PR claims the XPU work, and nointel/torch-xpu-opstracker covers it. This XPU fix is independent of whether#195208lands: XPU already diverges from CPU today, and no existing testasserts the faulting behavior.
Suggested XPU regression test: the same reproducer, mirroring upstream's
test_embedding_max_norm_zero_embedding_dim.github-actions commentedon Aug 29, 2026
alignment scan
2026-08-28, run33228378520[xpu-alignment] exponential_ underflows to exactly 0 for float16 on XPU, outside the distribution support
Upstream source
Fix exponential_ underflowing to exactly 0 for float16(OPEN, unmerged; fixes torch.multinomial selects zero-probability indices on CPU for float16, so exponential_ underflows to exactly 0 in the double to half cast pytorch/pytorch#192812).aten/src/ATen/native/cpu/DistributionTemplates.h,aten/src/ATen/native/cuda/DistributionTemplates.h,c10/util/safe_numerics.h(newc10::cast_no_underflow), andtest/test_torch.py.No XPU kernel is touched.
[2026-08-28T00:00:00Z, 2026-08-29T00:00:00Z).Observed XPU behavior
The exponential distribution has support
(0, inf), soTensor.exponential_()must never return exactly
0. Over 24e6 XPU draws per(dtype, lambd):No sample was non-finite or negative.
min_positiveat the failing rows is5.960e-08, exactly the smallest float16 subnormal, which is the signature of anarrowing cast flushing a nonzero sample to zero.
Root cause and target-path evidence
Upstream states the root cause as:
exponential_samples in a wider type andnarrows with
static_cast<scalar_t>; anything below float16's smallestsubnormal becomes an exact
0. XPU reproduces both halves of that:ExponentialFunctorinsrc/ATen/native/xpu/sycl/DistributionTemplates.h:854computes in
accscalar_tand returnsaccscalar_t, applying theeps/2floor in the accumulate type. For
lambd=65504that floor is4.88e-4 / 2 / 65504=3.7e-9, already below the half subnormal.DistributionElementwiseKernelFunctor::operator()(
src/ATen/native/xpu/sycl/DistributionTemplates.h:88and:92) writes thetransform result straight into the output:
outisscalar_t*, so this is the implicitaccscalar_t -> scalar_tnarrowing with no floor in the output dtype - the same shape as the
static_cast<scalar_t>upstream replaces.Target-path proof: the reproducer asserts
t.device.type == "xpu"on everydraw and synchronizes before reading, so the samples were produced by the XPU
kernel, not by a host fallback or setup tensor.
Reproducer
Environment
torch 2.15.0.dev20260826+xpu, Python 3.13.13 (/opt/conda/bin/python3.13),Intel(R) Arc(TM) Pro B60 Graphics,torch.xpu.is_available() == True, noenvironment warnings.
pytorch/pytorch#195077is not in this build.Ownership
The kernel is torch-xpu-ops code and the upstream PR does not touch it, so
landing
#195077leaves XPU broken.c10::cast_no_underflowwill be availablefrom
c10/util/safe_numerics.honce that PR lands, so the XPU change is asingle narrowing-site swap in
DistributionTemplates.h. Nopytorch/pytorchissue or PR claims the XPU work, and no
intel/torch-xpu-opstracker coversit -
intel/torch-xpu-ops#4020was considered and rejected, since it tracksstatistical-bias and moment assertion failures in
test_distributions_xpu.py,a different oracle and root cause.
CI impact:
#195077drops@onlyCUDAfromtest_exponential_no_zerointest/test_torch.pyand parametrizes it overlamin(1, 1024). That makesit device-generic, so it will run on XPU through
test/xpu/test_torch_xpu.pyand fail until this is fixed.
The XPU fix can land before or after
#195077: nothing asserts that zeros areproduced, and preserving an exact input
0keepsexponential_(inf) == 0intact.
github-actions commentedon Aug 29, 2026
alignment scan
2026-08-28, run33228378520[xpu-alignment] silu(-inf) returns NaN on XPU instead of the limit 0
Upstream source
Fix silu(-inf) returning NaN instead of the limit 0(OPEN, unmerged; fixes F.silu(torch.tensor(float('-inf'))) returns nan instead of 0 in PyTorch 2.7.0+cu128 pytorch/pytorch#160876, open since 2025-08-18).aten/src/ATen/native/cpu/Activation.cpp,aten/src/ATen/native/cuda/ActivationSiluKernel.cu,test/test_unary_ufuncs.py, and thenn.functional.siluOpInfo reference intorch/testing/_internal/common_methods_invocations.py. No XPU kernel istouched.
[2026-08-28T00:00:00Z, 2026-08-29T00:00:00Z).Observed XPU behavior
silu(x) = x * sigmoid(x)tends to0asx -> -inf, sosilu(-inf)must be0. On XPU it is NaN for every floating dtype:Large finite negatives (
-1e4,-1e3,-100) return-0.0correctly, so thisis specifically the
-inf / infform and not early flushing. The backward at-inf, whose limit is also0, is NaN for all four dtypes as well.The oracle is the mathematical limit, not CPU: CPU currently shares the same
defect, which is what
#195197fixes there.Root cause and target-path evidence
SiluFunctorinsrc/ATen/native/xpu/sycl/ActivationSiluKernels.cpp:26-35evaluates the algebraically equivalent but numerically unsafe form:
At
x = -infthis is-inf / (1 + inf)=-inf / inf= NaN. Upstream's CUDAfix adds an
if constexpr (!c10::is_complex<scalar_t>::value)guard returningscalar_t(0)at-inf; the XPU functor needs the same guard, and complexsilumust keep its current behavior since-infhas no complex ordering.SiluBackwardFunctor(:38-46) has the same structure throughopmath_t(1) / (opmath_t(1) + sycl::exp(-x_acc)); upstream's PR does notaddress the backward on any backend, so treat that as a related observation
rather than part of the parity change.
Target-path proof: the reproducer asserts the
siluoutput is on XPU andsynchronizes before reading. Independently, the
float64row differs from CPUin the low-order digits (
-0.2689414322376251on XPU vs-0.2689414213699951on CPU), which shows the printed values came from the XPU kernel rather than a
host fallback.
Reproducer
Environment
torch 2.15.0.dev20260826+xpu, Python 3.13.13 (/opt/conda/bin/python3.13),Intel(R) Arc(TM) Pro B60 Graphics,torch.xpu.is_available() == True, noenvironment warnings.
pytorch/pytorch#195197is not in this build.Ownership
The kernel is torch-xpu-ops code and the upstream PR does not touch it, so
landing
#195197leaves XPU as the only backend still returning NaN. Nopytorch/pytorchissue or PR claims the XPU work, and nointel/torch-xpu-opstracker covers it.
CI impact once
#195197lands:test_siluintest/test_unary_ufuncs.pygains a
silu(-inf) == 0assertion and the shared OpInfo reference becomesnp.where(x == -inf, 0.0, x / (1 + np.exp(-x))). Both are device-generic, sotest_siluandtest_reference_numerics_extremalwill fail on XPU throughtest/xpu/test_unary_ufuncs_xpu.py.Sequencing caveat: unlike the other units in this scan, the XPU change should
land with or after
#195197, not before it. XPU'stest_reference_numerics_*compares against the shared OpInfo reference, so returning
0while thatreference still evaluates the naive form would fail XPU CI in the opposite
direction. If
#195197is rejected upstream, this unit should be closed ratherthan implemented.
github-actions commentedon Aug 29, 2026
3 XPU alignment candidates need triage
3 reviewed candidates are waiting for approval:
issue-195185— [xpu-alignment] embedding_renorm_ derives the row width from stride(0) and faults on a zero-width embeddingpr-195077— [xpu-alignment] exponential_ underflows to exactly 0 for float16 on XPU, outside the distribution supportpr-195197— [xpu-alignment] silu(-inf) returns NaN on XPU instead of the limit 0Approve them one at a time with
@torchxpubot file <unit-id>.alignment scan
2026-08-28, run33228378520@laifenxiawucha @ZhaoqiongZ
github-actions commentedon Aug 30, 2026
XPU alignment run needs attention
This run did not finish cleanly:
scan-blocked-result:commit-1782e8ec673e736ffda3414fd921f3c1b1b62002:blocked-script-errorNothing was published for the affected part; see the gate artifact.
alignment scan
2026-08-29, run33287538032@laifenxiawucha @ZhaoqiongZ
121 remaining items
torchxpubot commentedon Nov 8, 2026
XPU alignment run completed with warnings
2026-11-07duplicate: 1,track-upstream: 1)No new XPU tracker was filed or drafted.
pr-203892—blocked-script-errorworkflow run
42437331929@laifenxiawucha @ZhaoqiongZ
torchxpubot commentedon Nov 9, 2026
XPU alignment run completed with warnings
2026-11-08track-upstream: 5)No new XPU tracker was filed or drafted.
issue-203969—blocked-platformissue-203979—blocked-envworkflow run
42549395667@laifenxiawucha @ZhaoqiongZ
torchxpubot commentedon Nov 10, 2026
Filed as #6127
alignment scan
2026-11-09, workflow run42740792617[xpu-alignment] [26-11-09] XPU segment_reduce accumulates fp16/bf16 in the input dtype: 4096 ones sum to 2048 (fp16) and 256 (bf16)
Summary
torch.segment_reduceon XPU keeps its running reduction value in the input dtype, so float16 and bfloat16sumandmeanstop growing once the partial sum passes the dtype's integer-resolution limit. A single segment of 4096 ones reduces to2048in float16 and256in bfloat16 instead of4096, andmeanreturns0.5and0.0625instead of1.0. Both expected values are exactly representable in either dtype, so this is accumulator loss, not representation error. The result is silently wrong: no warning, no error.Upstream source
high priorityandmodule: correctness (silent)) reports the same defect for the CPU kernel.aten/src/ATen/native/SegmentReduce.cppandaten/src/ATen/native/cuda/SegmentReduce.cuto accumulate inat::opmath_type<scalar_t>and adds a device-generic regression test. It does not touchintel/torch-xpu-ops.[2026-11-09T00:00:00Z, 2026-11-10T00:00:00Z)overpytorch/pytorch, frozen default-branch heada68f117948121cdff578ff7813c5c906ff529b57.Observed XPU behavior
Validated on XPU with
torch 2.16.0.dev20261109+xpu:All four cases reproduce the exact values upstream reports for CPU. The reference in each row is
torch.segment_reduce(data.float(), ...)computed on the same XPU device and cast back, so the comparison is XPU against XPU and is not a host/device artifact.Target path and root cause
segment_reduce_forward_kernelinsrc/ATen/native/xpu/sycl/SegmentReduceKernels.cpp:40. The accumulator is deduced from thescalar_tinitial value and never widened:For float16 every partial sum is rounded back to float16, so once the sum reaches 2^11 = 2048 adding 1.0 rounds to the same value and the sum stops advancing; for bfloat16 the limit is 2^8 = 256.
meaninherits the truncated sum because the division happens after the loop, still inscalar_t. The initial value isscalar_tat the dispatch site too (src/ATen/native/xpu/sycl/SegmentReduceKernels.cpp:231).Unlike CUDA, XPU has a single forward path (
segment_reduce_forward_kernel_impl, line 117) behind both_segment_reduce_lengths_kernel(line 268) and_segment_reduce_offsets_kernel(line 278), so lengths- and offsets-based calls are both affected and one accumulator change covers both.Target-path evidence: the lengths tensor and all four outputs are
xpu:0, andtorch.xpu.synchronize()is called before each value is read.Reproducer
Environment
Ownership
The XPU kernel carries its own copy of the accumulator. At the scanned head the same
scalar_taccumulation is present upstream inaten/src/ATen/native/cuda/SegmentReduce.cu(initial_value = initial_value + data), so XPU is currently a faithful port rather than a divergence. The upstream fix PR #204079 rewrites only the CPU and CUDA accumulators;src/ATen/native/xpu/sycl/SegmentReduceKernels.cppis untouched by it, so the XPU change is independent work in this repository and does not depend on #204079 landing.Stage of the upstream fix: proposed, not landed (#204079 is open against a ghstack base as of this scan). Its approach, accumulate in
at::opmath_type<scalar_t>and cast once when writing the output, is the one to mirror here. #204079 names two remaining upstream gaps that do not apply to the XPU kernel structure: the CUDA 1-Dmeanpath storing the sum in the output dtype, and the CPUprodbackward.Related, not covering this finding:
max/minbackward tied-gradient split. It does not change the forward accumulator.segment_reduceforward and is cross-referenced from #204045; it has no XPU scope.No open or closed
intel/torch-xpu-opstracker was found for the fp16/bf16 forward accumulation dtype (searchedsegment_reduce,opmath accumulation,fp16 bfloat16 accumulate sum, and PRs touchingSegmentReduce*).Regression test
test/xpu/test_segment_reductions_xpu.pyruns the upstream suite with no skips (test/xpu/skip_list_common.py:229maps it toNone). The device-generic test #204079 adds,TestSegmentReductions.test_reduced_precision_accumulation, will therefore run on XPU as soon as that PR lands and will fail until the XPU accumulator is widened. No existing XPU test covers this: the current cases use segments short enough thatscalar_taccumulation is exact.torchxpubot commentedon Nov 10, 2026
Filed as #6128
alignment scan
2026-11-09, workflow run42740792617[xpu-alignment] [26-11-09] XPU Tensor.renorm divides by norm + 1e-7, so renormalised rows land below max_norm (33% short at max_norm=1e-7)
Summary
Tensor.renorm/Tensor.renorm_on XPU scale a too-long row bymax_norm / (norm + 1e-7)instead ofmax_norm / norm, so the renormalised row never reachesmax_norm, which is what the docstring promises. The1e-7is absolute, so the error is about 2e-8 relative atmax_normnear 1 but grows without bound asmax_normshrinks: about 0.05% at1e-4, 4.8% at1e-6and 33% at1e-7. The guard is also unnecessary: the scaling branch only runs whennorm > max_norm >= 0, sonorm > 0and the division is always safe.Upstream source
+1e-7forF.embedding(max_norm=...),nn.Embedding,embedding_bagandTensor.renorm/renorm_on CPU.normdirectly inaten/src/ATen/native/cpu/RenormKernel.cpp,aten/src/ATen/native/cuda/RenormKernel.cu,aten/src/ATen/native/mps/kernels/RenormKernel.metal,aten/src/ATen/native/Embedding.cppandaten/src/ATen/native/cuda/Embedding.cu, and adds device-generic regressions. It does not touchintel/torch-xpu-ops.[2026-11-09T00:00:00Z, 2026-11-10T00:00:00Z)overpytorch/pytorch, frozen default-branch heada68f117948121cdff578ff7813c5c906ff529b57.Observed XPU behavior
Validated on XPU with
torch 2.16.0.dev20261109+xpu, float64:0.9999999800000003is exactly1.0 * 5.0 / (5.0 + 1e-7), the value upstream reports, so the XPU renorm scale factor carries the same absolute guard.Scope of what was measured, stated explicitly:
Tensor.renormin float64.F.embedding(..., max_norm=...)in float64 returned exactly1.0(scale0.20000000000000004) with zero relative shortfall atmax_norm1e-4,1e-6and1e-7. That is because the XPU embedding renorm uses a dtype-relative epsilon rather than upstream's absolute1e-7(see below), andnumeric_limits<double>::epsilon()is about 2.2e-16.accscalar_tisfloatandnumeric_limits<float>::epsilon()is 1.19e-7, the same order as upstream's1e-7, so a comparable shortfall is expected but was not exercised by this reproducer. It should be checked as part of the fix.Target path and root cause
Two separate XPU copies of the guard:
RenormKernel.cppis a faithful port of upstream's CUDA kernel at the scanned head (maxnorm_s / (norm + eps),eps = 1e-7).Embedding.cppalready deviates: upstream CUDA uses an absolutemax_norm / (sdata[0] + 1e-7), XPU usesnumeric_limits<accscalar_t>::epsilon(). After #204132 lands, upstream CPU/CUDA/MPS divide bynormexactly and both XPU copies are left adding an epsilon.Target-path evidence: the weight, index, embedding output and renorm output are all
xpu:0, andtorch.xpu.synchronize()is called before each value is read.Reproducer
Environment
Ownership
renorm_scale_factor_stubis registered by this repository (src/ATen/native/xpu/sycl/RenormKernel.cpp) and the embedding renorm kernel lives here too, so neither is reachable from the upstream fix. #204132 changes only CPU, CUDA and MPS; the XPU change is independent work in this repository and does not depend on #204132 landing.Stage of the upstream fix: proposed, not landed (#204132 is open against
mainas of this scan, and its own test plan states that no local rebuild or device run was performed and that CI is required). Its approach, drop the guard and divide bynorm, justified bynorm > max_norm >= 0, applies unchanged to both XPU copies.Related, not covering this finding:
embedding_renorm_defect in the same file: the row width came fromstride(0)instead ofsize(1). It did not touch the epsilon, and closing it did not fix the guard.No open
intel/torch-xpu-opstracker was found for the renorm epsilon (searchedrenorm,max_norm,renorm 1e-7 epsilon norm, and PRs touchingrenorm).Regression test
test/xpu/test_torch_xpu.pyruns the upstream device-generictest_torch.pysuite with no skips (test/xpu/skip_list_common.py:259maps it toNone). #204132 addsTestTorchDeviceType.test_renorm_exact_maxnorm, which asserts thattorch.tensor([[2e-6, 0.0]], device=device).renorm(2, 0, 1e-6).norm()equals1e-6withinatol=1e-8; in float32 the current XPU kernel returns about 9.524e-7, a 4.8e-8 miss, so that test will fail on XPU once the PR lands. #204132 also addsnn/test_embedding.pycoverage for the functional, module andembedding_bagentry points on accelerator devices, which will exercise theEmbedding.cppcopy. A fix here should additionally add a float32F.embedding(max_norm=...)case, since the float64 path masks the dtype-relative epsilon.torchxpubot commentedon Nov 10, 2026
XPU alignment run completed with warnings
2026-11-09needs-xpu-fix: 2,track-upstream: 5)Automatically filed:
issue-204045— [xpu-alignment] [26-11-09] XPU segment_reduce accumulates fp16/bf16 in the input dtype: 4096 ones sum to 2048 (fp16) and 256 (bf16) #6127issue-204119— [xpu-alignment] [26-11-09] XPU Tensor.renorm divides by norm + 1e-7, so renormalised rows land below max_norm (33% short at max_norm=1e-7) #6128Excluded units:
issue-204062—blocked-script-errorworkflow run
42740792617@laifenxiawucha @ZhaoqiongZ
daisyden commentedon Nov 10, 2026
label-issue: #5018
Root cause: not a defect; sink issue the alignment workflow posts to (.github/workflows/xpu_alignment.yml:28
ALIGNMENT_TRIAGE_ISSUE: '5018').typeTaskissue_typeempty; describes a standing workflow triage/posting channel, no failure reported.testtest: utmodulemodule: inframodule: infrapreserved; matches CI workflow sink (xpu_alignment.yml:28).priorityMediumApplied to this issue. Generated by a local
label-issuerun.torchxpubot commentedon Nov 11, 2026
alignment scan
2026-11-10, workflow run42943920909[xpu-alignment] [26-11-10] XPU multinomial(replacement=True) builds its CDF in the input dtype: bfloat16 resolves 847 of 10000 draws and a half row summing past 65504 returns index 0 for every draw
Upstream source
Compute multinomial internals in float for half and bfloat16(PR Compute multinomial internals in float for half and bfloat16 pytorch/pytorch#204161), committed 2026-11-10T09:09:13Z.pytorch/pytorchdefault-branch head3aad3844fc331821235a833579a71323af3c3eaf(GitHubcomparereports behind_by 0), so the change is landed upstream.The commit touched
aten/src/ATen/native/Distributions.cpp,aten/src/ATen/native/cuda/MultinomialKernel.cuandtest/distributions/test_distributions.py, and no XPU file. Its new regression test records the XPU gap rather than fixing it:Observed XPU behaviour
The XPU with-replacement kernel still does its renormalisation, prefix sum and binary search in the input dtype, so it reproduces both defects the commit describes for the pre-fix CUDA kernel:
max index 65405, so the whole upper half of the category range (indices >= 65536) is unreachable andupper_fractionis 0 rather than 0.5. CPU, from the same seed, resolves 9622 distinct withmax 131053. Upstream's figure for the broken CUDA kernel isabout 830.min 0 max 0 distinct 1) and exits cleanly; CPU returnsmin 312 max 69907 distinct 64. Note this signature differs from the CUDA one upstream describes: on XPU the overflow produces a silent wrong result, not a device-side assert.Target-path evidence
torch.multinomial(w_xpu, n, replacement=True)->multinomial_with_replacement_stub(XPU)->at::native::xpu::multinomial_kernelinsrc/ATen/native/xpu/sycl/MultinomialKernel.cpp. The reproducer assertsout.device.type == "xpu"and prints the result device for every call; the log showsxpu:0on both arms. In that file:renormRowsL1<scalar_t>accumulates and divides the row inscalar_t(lines 31-74), called viarenormRows(line 93);at::cumsum_out(prefixSum, normDist, 1)whereprefixSum = native::empty_like(self_v), i.e. stillscalar_t(lines 441-454);binarySearchForMultinomial<scalar_t>comparesscalar_tcumulative values (line 109).The single-sample path
sample_multinomial_once_kernelalready usesacc_type_device<scalar_t, kXPU>(line 388) and is not affected; only the with-replacement path needs the float promotion.Reproducer
Relevant output
Environment
Ownership
The defective arithmetic is in
intel/torch-xpu-ops(src/ATen/native/xpu/sycl/MultinomialKernel.cpp). Upstream fixed onlyaten/src/ATen/native/cuda/MultinomialKernel.cuand deliberately skipped XPU in the new test, so the parity work is not owned upstream. The fix mirrors the CUDA one: promote the renorm, the prefix sum and the search comparison toopmath_type<scalar_t>/floatfor half and bfloat16.Related trackers
Searched
intel/torch-xpu-opsandpytorch/pytorch; no open or closed issue covers XPU multinomial reduced-precision sampling. Same class of defect in other XPU kernels, not duplicates:segment_reduceaccumulates fp16/bf16 in the input dtype.linspace/logspacecompute the half/bfloat16 step in the output dtype.torchxpubot commentedon Nov 11, 2026
alignment scan
2026-11-10, workflow run42943920909[xpu-alignment] [26-11-10] XPU split_with_sizes_copy.out takes its byte-copy fast path for any dense input: wrong values for transposed and channels_last inputs, and a write past the output when the size-1 split dim has a large stride
Upstream source
[CUDA] Only take the split_with_sizes_copy.out fast path for dense, matching slices(PR [CUDA] Only take the split_with_sizes_copy.out fast path for dense, matching slices pytorch/pytorch#203892), committed 2026-11-10T04:51:40Z.pytorch/pytorchdefault-branch head3aad3844fc331821235a833579a71323af3c3eaf(GitHubcomparereports behind_by 0), so the change is landed upstream.The commit touched
aten/src/ATen/native/cuda/TensorShape.cuandtest/test_torch.py, and no XPU file. Its own description of the bug applies verbatim to the XPU kernel: the fast path "accepted any dense input and outputs, so a transposed input, or a channels_last input split into contiguous outputs, produced wrong values. It also used the split dimension's stride as the chunk size, so an arbitrary stride on a size-1 split dimension could cause writes past the output."Upstream recorded the XPU gap rather than fixing it; its new regression test is annotated:
Observed XPU behaviour
Running that test's seven layout cases against the CPU composite result as the oracle (every case first shown to hold on CPU), 3 of 7 fail on XPU:
torch.arange(12.).reshape(3, 4).t(), split[2, 2]on dim 0torch.zeros(64).as_strided((2, 1, 2), (2, 16, 1)), split[1]on dim 1(4, 3, 2, 5), split[2, 2]on dim 0The second case is an out-of-bounds device write, not just a wrong value.
Target-path evidence
torch.split_with_sizes_copy(x_xpu, sizes, dim, out=...)->split_with_sizes_copy_out_xpu->at::native::xpu::split_with_sizes_copy_out_xpu_kernelinsrc/ATen/native/xpu/sycl/TensorShapeKernels.cpp. The reproducer asserts that the input and every output tensor are onxpuand printsout[0].deviceper case; the log showsxpu:0for all seven.In that file:
split_with_sizes_copy_out_xpu_kernel(line 774) selects the byte-copy fast path onself.is_non_overlapping_and_dense()and the same predicate per output (lines 779-783) -- dense but non-canonical layouts are accepted, and nothing checks that each output stores its elements in the same order as the input slice;get_split_chunk_sizes(line 161) computessplit_size * tensor.stride(dim) * element_size, so a size-1 split dim with an arbitrary stride yields an oversized chunk and the copy runs past the destination.Upstream's fix computes chunk sizes and offsets from dimension sizes instead of
stride(dim), and restricts the fast path to dense, order-preserving slices; the equivalent change is needed inTensorShapeKernels.cpp.Reproducer
Relevant output
Environment
Ownership
The defective fast path is in
intel/torch-xpu-ops(src/ATen/native/xpu/sycl/TensorShapeKernels.cpp). Upstream fixed only the CUDA kernel and marked its regression test@skipIfXpuwith a message naming this exact XPU gap, so the parity work is not owned upstream. Landing the fix here also lets that upstream skip be removed.Related trackers
Searched
intel/torch-xpu-opsandpytorch/pytorch; no open tracker covers the fast-path layout gate or thestride(dim)chunk size. Related but distinct, both about a zero-length split dividing by zero in the same kernel family rather than about layout:test_split_with_sizes_copy_out_xpucrashes with SIGFPE, triggered by a zero-sized split. Fixing it would not fix the layout defect reported here, and vice versa.split_with_sizes_copywith a zero-length split size crashes the XPU worker process.torchxpubot commentedon Nov 11, 2026
alignment scan
2026-11-10, workflow run42943920909[xpu-alignment] [26-11-10] Sparse COO mul kills the XPU process with SIGFPE: the torch-xpu-ops copy of the intersection heuristic divides by prod(shape[:sparse_dim]) accumulated in an int
Upstream source
[Bug][Sparse] Multiplying empty sparse tensors with broadcastable shapes crashes due to integer division by zero, created 2026-11-10, still open.[sparse] Avoid division ..., open, not merged (mergedAtnull as of this review). It changes onlyaten/src/ATen/native/sparse/SparseBinaryOpIntersectionCommon.h(+3/-2) andtest/test_sparse.py.Upstream roots the SIGFPE in the coalesce heuristic
larger._nnz() / prod(larger.shape[:sparse_dim])and names two ways the product reaches 0: a zero-size sparse dim, and -- not in the issue, only in the PR -- thatstd::accumulate(..., 1, std::multiplies<int64_t>())keeps its accumulator in the type of the init value,int, so sparse sizes 65536 x 65536 truncate to 0.Observed XPU behaviour
Both variants kill the XPU process with SIGFPE (child returncode -8), after a control multiplication proves the XPU intersection path works:
torch.zeros(0, 3, device='xpu').to_sparse(1) * torch.zeros(0, 1, device='xpu').to_sparse(1)dies with SIGFPE. Expected result, per the issue and densetorch.zeros(0, 3) * torch.zeros(0, 1), is an empty sparse tensor of shape(0, 3). CPU dies the same way, which is the open upstream bug.sparse_cootensors of size(65536, 65536)with nnz 2 die with SIGFPE on XPU, while CPU returns the correct values[3.0, 8.0]. This asymmetry is XPU-specific:mul_out_sparse_cpu(aten/src/ATen/native/sparse/SparseTensorMath.cpp:1035) sends equal-size, coalesced sparse operands to a brute-force merge and never calls the intersection kernel, whereasmul_sparse_kernelinsrc/ATen/native/sparse/xpu/sycl/SparseTensorMathKernels.cpp:442falls through to_mul_sparse_sparse_outfor every sparse-sparse case except a zero-nnz short circuit. XPU therefore reaches the faulty division on inputs where CPU does not.Target-path evidence
Tensor.mulon sparse COO XPU tensors ->mul_out_sparse_xpu->xpu::mul_sparse_kernel->_mul_sparse_sparse_out->mul_sparse_sparse_out_stub(XPU), registered insrc/ATen/native/sparse/xpu/SparseBinaryOpIntersection.cpp:16toxpu::mul_sparse_sparse_kernelinsrc/ATen/native/sparse/xpu/sycl/SparseBinaryOpIntersectionKernels.cpp.The control multiplication printed
CONTROL device xpu:0 shape (2, 3) values [2.0, 4.0, 6.0, 12.0, 15.0, 18.0]before each crash, so the XPU intersection path executed; the crash then happened after theTARGET about to multiplyline and before any result, in host code.That torch-xpu-ops file carries its own copy of the upstream heuristic, byte-for-byte equivalent to the header at the scanned default-branch head
3aad3844fc331821235a833579a71323af3c3eaf:Because the XPU path never enters the upstream header, PR #204266 landing will not fix XPU. The same two-line change (accumulate in
int64_t, skip the division when the product is 0) has to be applied to this copy.Reproducer
Each variant aborts the process, so run them separately.
Relevant output
(-8 is SIGFPE.)
Environment
Ownership
The faulting division is in
intel/torch-xpu-ops. The upstream fix is still only proposed (PR #204266, open) and covers only the shared header, which the XPU dispatch path does not use, so this is independent XPU work whose fix does not depend on that PR landing. Worth fixing even ahead of it: the int-overflow variant crashes on XPU for inputs CPU handles correctly today.Related trackers
Searched
intel/torch-xpu-opsandpytorch/pytorch; no open or closed issue covers this XPU crash. Related but distinct:mulhangs for complex128/float64 on BMG (performance, not a crash)._masked_softmax), same class of defect in a different kernel.torch.add(dense, dense, out=sparse_csr)aborts on XPU.torchxpubot commentedon Nov 11, 2026
alignment scan
2026-11-10, workflow run42943920909[xpu-alignment] [26-11-10] XPU deterministic reflection_pad2d backward drops the right-zone gradient for columns that are in both reflection zones: max|grad - CPU| = 3.97 for pad=(3, 2, 4, 3)
Upstream source
Fix deterministic CUDA reflection_pad2d backward for large pads, open, not merged (mergedAtnull as of this review). Fixes use_deterministic_algorithms(True): CUDA reflection_pad2d backward returns wrong gradients for large pads pytorch/pytorch#203421 (open).The PR touches
aten/src/ATen/native/cuda/ReflectionPad.cu(+5/-2) andtest/test_nn.py, and no XPU file. Its root cause: the top-right and bottom-right corner terms sat inelse if (is_right)branches afterif (is_left), so they were skipped whenever a column is in both the left and the right reflection zone (pad_left + pad_right >= width - 1).Observed XPU behaviour
Under
torch.use_deterministic_algorithms(True), with the PR's own test shape -- a(2, 3, 5, 4)float64 input andpad = (3, 2, 4, 3)-- the XPU gradient disagrees with the CPU gradient computed from the identical input and the identicalgrad_output:pad=(1, 1, 1, 1)pad=(3, 2, 4, 3)The control isolates the defect to the overlapping zone: the kernel is correct when no column is in both zones. Gradients are silently wrong, with no error raised. For this shape
input_dim_x = 4,pad_left = 3,pad_right = 2, sois_leftholds for columns 1..3 andis_rightfor columns 1..2 -- columns 1 and 2 are in both and lose their right-zone contribution.Target-path evidence
F.pad(x_xpu, pad, mode='reflect').backward(...)with determinism enabled ->reflection_pad2d_backward_det_template(selected atsrc/ATen/native/xpu/sycl/ReflectionPadKernels.cpp:842byat::globalContext().deterministicAlgorithms()) ->reflection_pad2d_backward_det_kernel(line 310). The reproducer enables determinism, asserts the forward output andx.gradare onxpu, prints both devices (xpu:0), and callstorch.xpu.synchronize()before reading the gradient.The kernel, under a comment at line 307 saying it "Mirrors the CUDA deterministic implementation", carries exactly the structure the PR replaces:
The fix is the same as upstream's: make the two
is_rightblocks unconditionalif (is_right)so both corner contributions accumulate. Note the edge blocks further down (lines 388-395) already use independentifs, which is why only the corner terms are lost.Reproducer
Relevant output
Environment
Ownership
The defect is in
intel/torch-xpu-ops(src/ATen/native/xpu/sycl/ReflectionPadKernels.cpp) and is established here against the CPU gradient, independently of the upstream PR: the XPU deterministic backward is wrong today and the fix does not depend on PR #204276 landing. Upstream's fix is still at the proposed stage and touches only the CUDA kernel, so the XPU work is not owned upstream. The CUDA PR is worth tracking only as a reference for the shape of the change and for its regression testtest_ReflectionPad2d_deterministic_overlapping_pads, which is device-generic and should pass on XPU once this is fixed.Related trackers
Searched
intel/torch-xpu-opsandpytorch/pytorch; no open or closed issue covers the XPU deterministic reflection_pad2d backward. Related but distinct:replication_pad2d,grid_sample), a validation gap rather than a wrong gradient.use_deterministic_algorithms(True)branch (index_add_on bool).torchxpubot commentedon Nov 11, 2026
XPU alignment run completed with warnings
2026-11-10needs-xpu-fix: 4)Formal candidate drafts:
commit-500c6606e46ae107a69deb006bde5e90d578660b— [xpu-alignment] [26-11-10] XPU multinomial(replacement=True) builds its CDF in the input dtype: bfloat16 resolves 847 of 10000 draws and a half row summing past 65504 returns index 0 for every drawcommit-b0c56ca7a17bd5dd2c52dd724f9c18ac46a3bde5— [xpu-alignment] [26-11-10] XPU split_with_sizes_copy.out takes its byte-copy fast path for any dense input: wrong values for transposed and channels_last inputs, and a write past the output when the size-1 split dim has a large strideissue-204225— [xpu-alignment] [26-11-10] Sparse COO mul kills the XPU process with SIGFPE: the torch-xpu-ops copy of the intersection heuristic divides by prod(shape[:sparse_dim]) accumulated in an intpr-204276— [xpu-alignment] [26-11-10] XPU deterministic reflection_pad2d backward drops the right-zone gradient for columns that are in both reflection zones: max|grad - CPU| = 3.97 for pad=(3, 2, 4, 3)Automatic filing is limited to 3 candidates; review these drafts and create trackers manually.
commit-fb6d70c154a6e8a58ff72e907c7f9959650c827d—blocked-envissue-204215—blocked-envworkflow run
42943920909@laifenxiawucha @ZhaoqiongZ
torchxpubot commentedon Nov 12, 2026
Filed as #6162
alignment scan
2026-11-11, workflow run43139444140[xpu-alignment] [26-11-11] XPU grid_sampler_2d backward accumulates the fp16/bf16 grid gradient in the input dtype: 2048 unit contributions sum to 1024 (fp16) and 128 (bf16)
Summary
grid_sampler_2d_backwardon XPU keeps its grid-gradient accumulator in the input dtype, so for float16 and bfloat16 the per-channel sum stops growing once each tap falls below half a unit in the last place of the running sum. With 2048 channels that each contribute exactly1to the x-gradient and a coordinate scale of1, XPU returns[1024.0, 0.0]for float16 and[128.0, 0.0]for bfloat16, where the exact answer[2048.0, 0.0]is representable in both dtypes. float32 on the same device is exact, so this is accumulator loss, not representation error, and it is silent: no warning, no error.The practical effect is that half-precision
F.grid_samplebackward reports grid gradients that are too small by up to 16x for wide channel counts, which quietly stalls learning of the sampling grid (spatial transformers, optical-flow warps, deformable sampling).Upstream source
module: correctness (silent),module: numerical-stability,module: half,module: bfloat16,module: interpolation. The values were measured on ROCm (MI355X); the CUDA behaviour is derived from source and was not executed.aten/src/ATen/native/cuda/GridSampler.cu,aten/src/ATen/native/cuda/GridSampler.cuh,docs/source/notes/hip.rstandtest/test_nn.py; it is deliberately scoped to the ROCm build and leaves the CUDA build byte-identical. It does not touchintel/torch-xpu-ops, so it cannot cover XPU, and all three tests it adds are@onlyCUDA, so XPU CI will not surface this gap either.[2026-11-11T00:00:00Z, 2026-11-12T00:00:00Z)overpytorch/pytorch, frozen default-branch head125472c0cbd6259715738ed1a80cd0240f914ad1.Observed XPU behavior
The float16 and bfloat16 rows are the exact values upstream reports for ROCm. Both output masks are affected, which places the loss in the grid-gradient accumulation itself rather than in the
grad_inputscatter (the[False, True]mask skips the scatter entirely).Why
[2048.0, 0.0]is the exact answer: withalign_corners=Falseandinp_H = inp_W = 2, a grid coordinate of(0, 0)unnormalizes toix = iy = 0.5, so all four bilinear weights are0.25andgix_mult = inp_W / 2 = 1. Per channel the x-gradient is-nw_val * (iy_se - iy) + ne_val * (iy_sw - iy) - sw_val * (iy - iy_ne) + se_val * (iy - iy_nw), which for the input column pattern[0, 1]is-0 * 0.5 + 1 * 0.5 - 0 * 0.5 + 1 * 0.5 = 1; over 2048 channels that is exactly2048. The y-gradient cancels to0. Because each channel adds two0.5taps, float16 stalls at1024(there the ULP is1.0, so+0.5rounds back to even) and bfloat16 stalls at128for the same reason.Target path and root cause
aten/src/ATen/native/native_functions.yamlat the frozen head dispatchesgrid_sampler_2d_backwardtoXPU: grid_sampler_2d_backward_xpu, which this repository implements, so the call reaches XPU code and not a CPU fallback. Target-path evidence in the run: every result row reportsdevice=xpu:0,torch.xpu.synchronize()is called before each value is read, and the float32 control on the same device and same kernel is exact, which rules out a harness or host/device artifact.The 2-D bilinear backward kernel declares the grid-gradient accumulator in
scalar_tand never widens it:The loop at
src/ATen/native/xpu/sycl/GridSampler.cpp:395walks allCchannels and rounds the running sum back toscalar_ton every tap, so once the sum reaches 2^10 (float16) or 2^7 (bfloat16) relative to the tap size it stops advancing. The coordinate scalegix_multis applied only after the loop, so widening it alone would not help. The forward kernel in the same file already computes inat::opmath_type<scalar_t>(src/ATen/native/xpu/sycl/GridSampler.cpp:65,104), which is why only the backward grid gradient is wrong.Two sibling kernels in the same file have the same narrow accumulator and are not separately reproduced here:
src/ATen/native/xpu/sycl/GridSampler.cpp:531-532, stored at583-584.src/ATen/native/xpu/sycl/GridSampler.cpp:1299-1300, stored at1485-1487.The 3-D bicubic backward kernel already accumulates in
opmath_tand casts once at the store (src/ATen/native/xpu/sycl/GridSampler.cpp:1619-1621,1665-1667), so the intended style is already present in this file.Suggested fix: accumulate
gix/giy(andgiz) inat::opmath_type<scalar_t>, apply the coordinate multiplier in that type, and cast once when writinggGrid_ptr_*, matching lines 1619-1667. Upstream #204495 additionally keeps a per-channel partial for reduced precision to limit intermediate overflow and cancellation; that refinement is worth reviewing, but the accumulator width is the part that produces the numbers above.Reproducer
This is the upstream snippet with
device="cuda"changed to"xpu"; shapes, dtypes, the expand/contiguous layout, both output masks and the directtorch.ops.aten.grid_sampler_2d_backwardcall are unchanged, and the float32 row is an added control.Environment
The reproducer ran unmodified as
python3.13 -I -uwith no network access and exited0in 3.5 s.Ownership
The XPU kernel is independent code in this repository:
grid_sampler_2d_backward_xpu(src/ATen/native/xpu/sycl/GridSampler.cpp:676) is dispatched directly fromnative_functions.yamland shares nothing withaten/src/ATen/native/cuda/GridSampler.cuh. The only upstream fix in flight (#204495) is scoped to the ROCm build, leaves CUDA unchanged, and does not modify this repository, so no upstream change will fix XPU. Searches ofpytorch/pytorchfor XPU-scoped grid-sampler issues or PRs returned nothing.No open
intel/torch-xpu-opsissue covers this work. The closest existing items are different defects:grid_sample; an error-checking gap, not accumulator width.grid_samplebicubic with 5-D input on XPU; a feature gap, unrelated to precision.Related accumulator-width parity work already tracked separately: #6127 (
segment_reducefp16/bf16 accumulation) and #5722 (nll_loss2dfp16 global atomics). This issue is the same class of defect in a different kernel and does not overlap their code.Suggested verification once fixed: the reproducer above must print
[2048.0, 0.0]for float16 and bfloat16; upstream'stest_grid_sample_2d_backward_low_precision_grid_grad(added by #204495, currently@onlyCUDA) is the natural regression test to mirror for XPU.torchxpubot commentedon Nov 12, 2026
XPU alignment run completed with warnings
2026-11-11duplicate: 2,needs-xpu-fix: 1,track-upstream: 3)Automatically filed:
issue-204496— [xpu-alignment] [26-11-11] XPU grid_sampler_2d backward accumulates the fp16/bf16 grid gradient in the input dtype: 2048 unit contributions sum to 1024 (fp16) and 128 (bf16) #6162Excluded units:
issue-204446—blocked-script-errorworkflow run
43139444140@laifenxiawucha @ZhaoqiongZ