diff --git a/src/ATen/native/xpu/SummaryOps.cpp b/src/ATen/native/xpu/SummaryOps.cpp index 0f5cbe43506..98f0d8c42ad 100644 --- a/src/ATen/native/xpu/SummaryOps.cpp +++ b/src/ATen/native/xpu/SummaryOps.cpp @@ -55,6 +55,13 @@ Tensor& _histc_out_xpu( const Scalar& min, const Scalar& max, Tensor& result) { + TORCH_CHECK( + self.dtype() == result.dtype(), + "torch.histogram: input tensor and hist tensor should", + " have the same dtype, but got input ", + self.dtype(), + " and hist ", + result.dtype()); auto ret = _histc_xpu(self, bins, min, max); at::native::resize_output(result, ret.sizes()); result.copy_(ret); diff --git a/test/regressions/test_histc.py b/test/regressions/test_histc.py new file mode 100644 index 00000000000..65646bbbda4 --- /dev/null +++ b/test/regressions/test_histc.py @@ -0,0 +1,35 @@ +# Copyright 2020-2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 + +# Owner(s): ["module: intel"] + +import torch +from torch.testing._internal.common_utils import run_tests, TestCase + + +class TestHistc(TestCase): + def test_histc_out_rejects_mismatched_dtype(self): + # Regression for intel/torch-xpu-ops#5237: _histc_out_xpu finished + # with result.copy_(ret), so a float histogram written into an + # integral out= was silently truncated. CPU rejects this call. + x = torch.linspace(1, 8, 8, device="xpu", dtype=torch.float32) + out = torch.empty(4, device="xpu", dtype=torch.int64) + + with self.assertRaisesRegex(RuntimeError, "should have the same dtype"): + torch.histc(x, bins=4, min=0, max=8, out=out) + + def test_histc_out_matching_dtype_still_works(self): + x = torch.linspace(1, 8, 8, device="xpu", dtype=torch.float32) + out = torch.empty(0, device="xpu", dtype=torch.float32) + + torch.histc(x, bins=4, min=0, max=8, out=out) + self.assertEqual(out, torch.histc(x, bins=4, min=0, max=8)) + + +if __name__ == "__main__": + run_tests() diff --git a/test/xpu/skip_list_common.py b/test/xpu/skip_list_common.py index 36c743e48fb..da171c8e005 100644 --- a/test/xpu/skip_list_common.py +++ b/test/xpu/skip_list_common.py @@ -183,7 +183,6 @@ # Exception: The supported dtypes for linalg.multi_dot on device type xpu are incorrect! "test_dtypes_linalg_multi_dot_xpu", # For CUDA it's skipped explicitly in common_methods_invocations.py in upstream. We can skip it here - "test_out_histc_xpu_float32", "test_out_mean_xpu_float32", # FakeTensor mismatch in outputs_alias_inputs for aten.view.default # Known upstream issue: https://github.com/pytorch/pytorch/issues/159150 diff --git a/test/xpu/xpu_test_utils.py b/test/xpu/xpu_test_utils.py index ae3b325c1a1..bdb6af08a66 100644 --- a/test/xpu/xpu_test_utils.py +++ b/test/xpu/xpu_test_utils.py @@ -1070,6 +1070,23 @@ def gen_xpu_wrappers(op_name, wrappers): else: wrapper.device_type = "xpu" replaced = True + elif ( + isinstance(wrapper.device_type, (list, tuple)) + and "xpu" in wrapper.device_type + and unittest.expectedFailure in wrapper.decorators + and (op_name, wrapper.test_name) in _cuda_xfail_xpu_pass + ): + # Upstream may scope one xfail to several devices at + # once (device_type=("cuda", "xpu")). Drop XPU from + # the scope so a test that now passes on XPU does + # not report an unexpected success. + replaced = True + new_wrapper = copy.copy(wrapper) + new_wrapper.device_type = tuple( + d for d in wrapper.device_type if d != "xpu" + ) + wrapper_xpu.append(new_wrapper) + continue elif ( wrapper.device_type is None and unittest.expectedFailure in wrapper.decorators