[xpu-alignment] embedding_renorm_ derives the row width from stride(0) and faults on a zero-width embedding
- Dominant language
- Python
- Stars
- 113
- Forks
- 128
- Avg merge
- 5d 13h
- Merged PRs (30d)
- 107
Description
### 🐛 Describe the bug
## Upstream source
- Issue: https://github.com/pytorch/pytorch/issues/195185 - `[CUDA] illegal memory read on renorm_kernel` (OPEN, created 2026-08-28).
- Proposed upstream fix: https://github.com/pytorch/pytorch/pull/195208 (OPEN, unmerged). It changes `aten/src/ATen/native/cuda/Embedding.cu` only, and its regression test is `@onlyOn(["cuda"])`.
- Alignment scan window: `[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-width
weight fails on XPU:
```
weight: torch.Size([20, 0]) (1, 1) 0 xpu:0 | stride(0)= 1 size(1)= 0
cpu out: (1, 0)
RESULT: confirmed
reason: XPU embedding_renorm_ on a zero-width weight failed: level_zero backend failed with error: 40 (UR_RESULT_ERROR_OUT_OF_RESOURCES)
```
CPU, given the identical inputs, returns shape `(1, 0)` cleanly. The oracle here
is CPU plus the upstream signature, not a tolerance comparison.
## Root cause and target-path evidence
`src/ATen/native/xpu/sycl/Embedding.cpp:237` takes the same shortcut upstream
names as the CUDA root cause:
```cpp
int dim = self.stride(0);
```
`torch.empty(20, 0).stride()` is `(1, 1)`, so `dim` becomes `1` while the real
row width `self.size(1)` is `0`. `dim` is passed to
`embedding_renorm_template`, and `RenormKernelFunctor::operator()`
(`src/ATen/native/xpu/sycl/Embedding.cpp:100-141`) then runs its accumulation
loop once and dereferences `weights_[base_index]`:
```cpp
for (int i = tid; i < dim_; i += sgSize) {
auto x = static_cast(weights_[base_index + i * weights_stride1_]);
```
The `(20, 0)` weight has zero elements, so that pointer has no backing
allocation - the same invalid read compute-sanitizer reports for CUDA. The fix
is the same one-line change: use `self.size(1)`. The kernel already receives
`weights_stride0`/`weights_stride1` separately for indexing, so it does not
depend on the tensor being contiguous, and `dim == 0` makes both loops execute
zero times without skipping the launch.
Target-path proof that this is the XPU kernel and not setup data or an
unsupported input:
- the log records the weight as resident on `xpu:0` and in exactly the
`stride(0)=1, size(1)=0` state the defect requires;
- the CPU reference ran first on the same inputs and succeeded, so this is not
an input-validation rejection;
- `embedding_renorm_` is dispatched to XPU via `embedding_renorm_xpu_` in
`src/ATen/native/xpu/Embedding.cpp:39`, so no fallback is involved;
- the runner's environment probe was clean and five other reproducers did heavy
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 either
way the oracle is violated on the XPU path.
## Reproducer
```python
import torch
import torch.nn.functional as F
weight = torch.empty((20, 0), dtype=torch.float32, device="xpu")
indices = torch.tensor([0], dtype=torch.int64, device="xpu")
print("cpu:", tuple(F.embedding(indices.cpu(), weight.cpu(), max_norm=1.0, norm_type=2.0).shape))
out = F.embedding(indices, weight, max_norm=1.0, norm_type=2.0)
torch.xpu.synchronize()
print("xpu:", tuple(out.shape)) # expected (1, 0)
```
## 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`, no
environment warnings. Neither upstream fix candidate is present in this build.
## Ownership
The kernel is torch-xpu-ops code. `pytorch/pytorch#195208` fixes only the CUDA
kernel and adds a CUDA-only test, so nothing upstream will fix or detect the XPU
copy. No `pytorch/pytorch` issue or PR claims the XPU work, and no
`intel/torch-xpu-ops` tracker covers it. This XPU fix is independent of whether
`#195208` lands: XPU already diverges from CPU today, and no existing test
asserts the faulting behavior.
Suggested XPU regression test: the same reproducer, mirroring upstream's
`test_embedding_max_norm_zero_embedding_dim`.
### Versions
--
Contributor guide
Assessment
This issue has not been assessed yet.