已合并
fix: Fall back to the aclop path for reshaped Nx1 column vectors #42471
fix: Fall back to the aclop path for reshaped Nx1 column vectors #42471
已合并
21xiu创建于 7月23日
2 个文件变更+34-0
@@ -228,6 +228,28 @@ class TestNpuFormatCastAclnn(TestCase):
228 with self.assertRaises(RuntimeError):228 with self.assertRaises(RuntimeError):
229 torch_npu.npu_format_cast(nz_t, ACL_FORMAT_ND)229 torch_npu.npu_format_cast(nz_t, ACL_FORMAT_ND)
230 230 
231+ # ------------------------------------------------------------------ #
232+ # Group 7: View guard — 2D column-vector (Nx1) fallback to aclop
233+ # ------------------------------------------------------------------ #
234+ # When a 2D contiguous tensor is a view (storage shape != current shape)
235+ # and the target is FRACTAL_NZ, the aclnn path is skipped to avoid
236+ # downstream precision issues. The aclop fallback is exercised here.
237+ # Example: storage [1, N] viewed as [N, 1] (Nx1 column vector).
238+ 
239+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
240+ def test_2d_view_nx1_nd_to_nz_format_id(self):
241+ """View [1, N] -> [N, 1]: format cast to NZ still succeeds."""
242+ # Create storage [1, N], then view as [N, 1]
243+ N = 16
244+ t = torch.rand(1, N).half().npu()
245+ t_view = t.t() # contiguous, Nx1 column vector
246+ self.assertTrue(t_view.is_contiguous())
247+ 
248+ out = torch_npu.npu_format_cast(t_view, ACL_FORMAT_FRACTAL_NZ)
249+ self.assertEqual(torch_npu.get_npu_format(out), ACL_FORMAT_FRACTAL_NZ)
250+ self.assertEqual(out.shape, (N, 1))
251+ self.assertEqual(out.storage()[1], t_view.storage()[1])
252+ 
231 253 
232class TestNpuFormatCastDtypeParam(TestCase):254class TestNpuFormatCastDtypeParam(TestCase):
233 """255 """
@@ -123,6 +123,18 @@ std::tuple<bool, int64_t, c10::SmallVector<int64_t, SIZE>> MaybeUseAclnnNpuForma
123 if (!FormatHelper::IsBaseFormatType(src) && !src.is_contiguous()) {123 if (!FormatHelper::IsBaseFormatType(src) && !src.is_contiguous()) {
124 return std::make_tuple(false, dstFormat, outputShape);124 return std::make_tuple(false, dstFormat, outputShape);
125 }125 }
126+ // Guard: when casting a 2D contiguous tensor from ND to FRACTAL_NZ, if the
127+ // tensor's current shape differs from its storage shape (base_sizes_), it means
128+ // it is a view (e.g. transpose). Downstream ops may encounter precision
129+ // issues, so the aclnn path is not supported for this case.
130+ // Fall back to the aclop path to stay safe.
131+ // Example: storage [1, N] viewed as [N, 1] (Nx1 column vector).
132+ auto src_desc = torch_npu::NPUBridge::GetNpuStorageImpl(src)->npu_desc_;
133+ if (src_desc.npu_format_ == ACL_FORMAT_ND && acl_format == ACL_FORMAT_FRACTAL_NZ &&
134+ src.is_contiguous() && src.sizes().size() == 2 && src_desc.base_sizes_.size() == 2 && src.sizes()[1] == 1 &&
135+ (src_desc.base_sizes_[0] != src.sizes()[0] || src_desc.base_sizes_[1] != src.sizes()[1])) {
136+ return std::make_tuple(false, dstFormat, outputShape);
137+ }
126 if (IsAclnnFormatCastSupported() && aclnnNpuFormatCastExist) {138 if (IsAclnnFormatCastSupported() && aclnnNpuFormatCastExist) {
127 auto acl_src = ConvertType(srcWrapper);139 auto acl_src = ConvertType(srcWrapper);
128 auto api_ret = GetFormat(acl_src, acl_format, customizeAcltype, &dstStorageShape,140 auto api_ret = GetFormat(acl_src, acl_format, customizeAcltype, &dstStorageShape,