test_decomp_xpu.py::TestDecompXPU::test_quick_mv_xpu_uint8 - Tensor-likes are not equal! (mv decomposition overflows uint8 instead of saturating)
- Dominant language
- Python
- Stars
- 113
- Forks
- 128
- Avg merge
- 5d 9h
- Merged PRs (30d)
- 112
Description
### 🐛 Describe the bug
`test_decomp.py::TestDecompXPU::test_quick_mv_xpu_uint8` fails: the `aten.mv` **decomposition** and the **eager** kernel disagree for `uint8` inputs because the two paths handle integer overflow differently. One path wraps modulo 256, the other saturates at 255.
```
FAILED [0.0061s] test_decomp.py::TestDecompXPU::test_quick_mv_xpu_uint8 - Exception: Tensor-likes are not equal!
Mismatched elements: 3 / 5 (60.0%)
Greatest absolute difference: 253 at index (0,)
Greatest relative difference: 126.5 at index (0,)
mv.default
args = (tensor([[2, 2, 5, 0, 3, 9, 9, 7, 8, 8],
[0, 4, 0, 3, 7, 4, 1, 2, 6, 1],
[9, 6, 2, 4, 2, 9, 9, 6, 5, 9],
[2, 4, 8, 4, 0, 4, 6, 0, 8, 4],
[5, 8, 7, 2, 5, 7, 5, 8, 5, 5]], device='xpu:0', dtype=torch.uint8), tensor([0, 8, 8, 4, 0, 7, 3, 8, 5, 2], device='xpu:0', dtype=torch.uint8))
kwargs = {}
Caused by sample input at index 0: SampleInput(input=Tensor[size=(5, 10), device="xpu:0", dtype=torch.uint8], args=TensorList[Tensor[size=(10,), device="xpu:0", dtype=torch.uint8]], kwargs={}, broadcasts_input=False, name='')
To execute this test, run the following from the base repo dir:
PYTORCH_OPINFO_SAMPLE_INPUT_INDEX=0 python test/test_decomp.py TestDecompXPU.test_quick_mv_xpu_uint8
```
### Root cause
The `mv` decomposition in [`torch/_decomp/decompositions.py`](https://github.com/pytorch/pytorch/blob/main/torch/_decomp/decompositions.py#L5156) rewrites the op as an elementwise multiply followed by a reduction:
```python
@register_decomposition(aten.mv)
@out_wrapper(exact_dtype=True)
@pw_cast_for_opmath
def mv(self, vec):
...
return (self * vec).sum(dim=1)
```
`pw_cast_for_opmath` is defined as:
```python
pw_cast_for_opmath = partial(
type_casts, type_promotion=utils.ELEMENTWISE_TYPE_PROMOTION_KIND.DEFAULT
)
```
With `ELEMENTWISE_TYPE_PROMOTION_KIND.DEFAULT`, `uint8` inputs get a `uint8` computation dtype — the wrapper only widens **floating point** types to an opmath type, it does **not** widen narrow integers to a wider integer accumulator. So the `.sum(dim=1)` result is truncated back into `uint8` and wraps, whereas the eager `mv` kernel accumulates in a wider type and clamps on store.
Verifying with row 0 of the sample input reproduces the reported numbers exactly:
```
row0 = [2, 2, 5, 0, 3, 9, 9, 7, 8, 8]
vec = [0, 8, 8, 4, 0, 7, 3, 8, 5, 2]
true dot product = 258 # overflows uint8 (max 255)
wraparound (mod 256) = 2
saturated = 255
absolute difference = 255 - 2 = 253 <-- matches "Greatest absolute difference: 253"
relative difference = 253 / 2 = 126.5 <-- matches "Greatest relative difference: 126.5"
```
No individual product overflows here (all are < 256); only the accumulated sum (258) exceeds the `uint8` range. That is why exactly the rows whose dot product exceeds 255 mismatch — 3 of 5 rows, consistent with the reported 60%.
This is an **upstream, device-agnostic** decomposition/type-promotion issue rather than an XPU kernel bug. It surfaces on XPU because `uint8` is exercised for `mv` in `test_decomp` here; there is no guard for it upstream:
- `CROSS_REF_EXCLUDE_SET` in [`test/test_decomp.py`](https://github.com/pytorch/pytorch/blob/main/test/test_decomp.py) contains **no** `mv` entry (it only has `uint8` exclusions for `linspace` and some `interpolate`/`upsample_bilinear` variants).
- `test/xpu/skip_list_common.py` → `"test_decomp_xpu.py"` currently lists only slow-test skips, nothing for `mv`.
Possibly related but **not** the same root cause: #2439 (`test_quick_addmv_xpu_float64`, oneDNN float accuracy) and #2474 (`test_decomp` accuracy once dtypes were aligned in `op_db`).
### Suggested resolution
Either of:
1. Skip/exclude integer dtypes for `mv` in `test_decomp` upstream (add an `mv` + integral-dtype entry to `CROSS_REF_EXCLUDE_SET`), and/or
2. Fix the decomposition to accumulate in a wider integer dtype for narrow integer inputs so it matches eager overflow semantics.
As a short-term unblock for XPU CI, `test_quick_mv_xpu_uint8` can be added to the `"test_decomp_xpu.py"` entry in `test/xpu/skip_list_common.py`.
### Versions
Extracted from the CI log (full `collect_env.py` output not captured in the run):
```
PyTorch test dir: /var/lib/jenkins/pytorch
Python: 3.10 (/opt/conda/envs/py_3.10)
Device: xpu:0
Test suite: test_decomp.py (TestDecompXPU)
```
The issue also occur on addmv and addmm
```
=========================== short test summary info ============================
2026-08-31T11:39:56.7439377Z FAILED [0.0109s] test_decomp.py::TestDecompXPU::test_quick_addmv_xpu_uint8 - Exception: Tensor-likes are not equal!
2026-08-31T11:39:56.7439383Z
2026-08-31T11:39:56.7439524Z Mismatched elements: 5 / 5 (100.0%)
2026-08-31T11:39:56.7439685Z Greatest absolute difference: 151 at index (1,)
2026-08-31T11:39:56.7439853Z Greatest relative difference: inf at index (0,)
2026-08-31T11:39:56.7439974Z addmv.default
2026-08-31T11:39:56.7440319Z args = (tensor([2, 2, 5, 0, 3], device='xpu:0', dtype=torch.uint8), tensor([[0, 8, 8, 4, 0, 7, 3, 8, 5, 2],
2026-08-31T11:39:56.7440456Z [9, 7, 4, 7, 4, 9, 6, 6, 3, 9],
2026-08-31T11:39:56.7440614Z [1, 0, 8, 8, 7, 0, 3, 5, 3, 0],
2026-08-31T11:39:56.7440744Z [2, 5, 7, 2, 6, 8, 9, 0, 1, 9],
2026-08-31T11:39:56.7441176Z [3, 0, 2, 6, 4, 2, 3, 6, 7, 3]], device='xpu:0', dtype=torch.uint8), tensor([8, 7, 3, 3, 1, 1, 0, 5, 9, 3], device='xpu:0', dtype=torch.uint8))
2026-08-31T11:39:56.7441323Z kwargs = {'beta': 0.2, 'alpha': 0.6}
2026-08-31T11:39:56.7441328Z
2026-08-31T11:39:56.7442322Z Caused by sample input at index 1: SampleInput(input=Tensor[size=(5,), device="xpu:0", dtype=torch.uint8], args=TensorList[Tensor[size=(5, 10), device="xpu:0", dtype=torch.uint8], Tensor[size=(10,), device="xpu:0", dtype=torch.uint8]], kwargs={'beta': '0.2', 'alpha': '0.6'}, broadcasts_input=False, name='')
2026-08-31T11:39:56.7442329Z
2026-08-31T11:39:56.7442665Z To execute this test, run the following from the base repo dir:
2026-08-31T11:39:56.7443031Z PYTORCH_OPINFO_SAMPLE_INPUT_INDEX=1 python test/test_decomp.py TestDecompXPU.test_quick_addmv_xpu_uint8
```
```
2026-09-02T08:17:18.0585898Z =========================== short test summary info ============================
2026-09-02T08:17:18.0586298Z FAILED [0.0082s] test_decomp.py::TestDecompXPU::test_quick_addmm_xpu_int8 - Exception: Tensor-likes are not equal!
2026-09-02T08:17:18.0586305Z
2026-09-02T08:17:18.0586448Z Mismatched elements: 2 / 6 (33.3%)
2026-09-02T08:17:18.0586630Z Greatest absolute difference: 252 at index (1, 2)
2026-09-02T08:17:18.0586839Z Greatest relative difference: 2.3617022037506104 at index (1, 1)
2026-09-02T08:17:18.0586996Z addmm.default
2026-09-02T08:17:18.0587224Z args = (tensor([-8], device='xpu:0', dtype=torch.int8), tensor([[ 0, -9],
2026-09-02T08:17:18.0587437Z [ 6, 9]], device='xpu:0', dtype=torch.int8), tensor([[-3, -4, -3],
2026-09-02T08:17:18.0587618Z [ 0, -5, -4]], device='xpu:0', dtype=torch.int8))
2026-09-02T08:17:18.0587753Z kwargs = {'beta': 3, 'alpha': 2}
2026-09-02T08:17:18.0587759Z
2026-09-02T08:17:18.0588700Z Caused by sample input at index 2: SampleInput(input=Tensor[size=(1,), device="xpu:0", dtype=torch.int8], args=TensorList[Tensor[size=(2, 2), device="xpu:0", dtype=torch.int8], Tensor[size=(2, 3), device="xpu:0", dtype=torch.int8]], kwargs={'alpha': '2', 'beta': '3'}, broadcasts_input=True, name='')
2026-09-02T08:17:18.0588740Z
2026-09-02T08:17:18.0588964Z To execute this test, run the following from the base repo dir:
2026-09-02T08:17:18.0589337Z PYTORCH_OPINFO_SAMPLE_INPUT_INDEX=2 python test/test_decomp.py TestDecompXPU.test_quick_addmm_xpu_int8
2026-09-02T08:17:18.0589343Z
```
Contributor guide
Research direction
Start with torch/_decomp/decompositions.py and test/test_decomp.py, then reproduce the listed mv, addmv, and addmm failures with their commands. Check the XPU skip configuration in test/xpu/skip_list_common.py and the CROSS_REF_EXCLUDE_SET before choosing the scope. Done means the affected integer cases no longer disagree between decomposition and eager behavior, with focused tests passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100