diff --git a/aten/src/ATen/native/NaiveConvolutionTranspose2d.cpp b/aten/src/ATen/native/NaiveConvolutionTranspose2d.cpp index 799b5ffa2cd..0748194d6a0 100644 --- a/aten/src/ATen/native/NaiveConvolutionTranspose2d.cpp +++ b/aten/src/ATen/native/NaiveConvolutionTranspose2d.cpp @@ -78,8 +78,8 @@ static inline void slow_conv_transpose2d_shape_check( if (weight.defined()) { TORCH_CHECK( - weight.numel() != 0 && (weight.dim() == 2 || weight.dim() == 4), - "non-empty 2D or 4D weight tensor expected, but got: ", + (weight.dim() == 2 || weight.dim() == 4), + "2D or 4D weight tensor expected, but got: ", weight.sizes()); if (bias.defined()) { check_dim_size(bias, 1, 0, weight.size(1)); diff --git a/aten/src/ATen/native/NaiveConvolutionTranspose3d.cpp b/aten/src/ATen/native/NaiveConvolutionTranspose3d.cpp index 773eb2542ee..b6edcfd6563 100644 --- a/aten/src/ATen/native/NaiveConvolutionTranspose3d.cpp +++ b/aten/src/ATen/native/NaiveConvolutionTranspose3d.cpp @@ -98,8 +98,8 @@ static inline void slow_conv_transpose3d_shape_check( if (weight.defined()) { /* TODO: TORCH_CHECK just have 2 args: condition and message */ TORCH_CHECK( - weight.numel() != 0 && weight.dim() == 5, - "non-empty 5D (n_output_plane x n_input_plane x kernel_depth", + weight.dim() == 5, + "5D (n_output_plane x n_input_plane x kernel_depth", " x kernel_height x kernel_width) tensor ", "expected for weight, but got: ", weight.sizes()); diff --git a/test/nn/test_convolution.py b/test/nn/test_convolution.py index fbe84a71300..d920b053c25 100644 --- a/test/nn/test_convolution.py +++ b/test/nn/test_convolution.py @@ -40,6 +40,7 @@ from torch.testing._internal.common_device_type import ( skipCUDAIfRocmVersionLessThan, skipMeta, skipMPS, + skipXLA, ) from torch.testing._internal.common_dtype import ( floating_and_complex_types_and, @@ -1749,6 +1750,29 @@ class TestConvolutionNNDeviceType(NNTestCase): actual = F.conv2d(x, y, padding="same", dilation=3) self.assertEqual(expect, actual, rtol=rtol, atol=atol) + @dtypes(torch.float) + # aten/src/ATen/native/mps/OperationUtils.mm: TORCH_INTERNAL_ASSERT([srcBuf length] > 0, "Placeholder tensor is empty!"); on MPS + @expectedFailureMPS + @skipXLA + def test_ConvTranspose_output_channels_0(self, device, dtype): + class Model(nn.Module): + def __init__(self, operator, dim): + super().__init__() + self.op = eval( + f"torch.nn.{operator}{dim}d(in_channels=1, out_channels=0, kernel_size={tuple([1] * dim)})" + ) + + def forward(self, x): + x = self.op(x) + return x + + for dim in [1, 2, 3]: + x = torch.randn([1] * (dim + 1), device=device, dtype=dtype) + model = Model("ConvTranspose", dim).to(device).to(dtype=dtype) + y = model(x) + self.assertEqual(y.numel(), 0) + self.assertEqual(x.shape[1:], y.shape[1:]) + @dtypes(torch.float, torch.cfloat) def test_conv3d_same_padding(self, device, dtype): if dtype is torch.cfloat: