已合并
trans npuformat cast from aclop to aclnn and fix 1d npu format cast fallback #38058
shawnylee233创建于 6月10日
trans npuformat cast from aclop to aclnn and fix 1d npu format cast fallback #38058
已合并
shawnylee233创建于 6月10日
3 个文件变更+723-4
@@ -3,10 +3,644 @@ import torch
3 3 
4import torch_npu4import torch_npu
5from torch_npu.testing.testcase import TestCase, run_tests5from torch_npu.testing.testcase import TestCase, run_tests
6-from torch_npu.testing.common_utils import create_common_tensor6+from torch_npu.testing.common_utils import create_common_tensor, SupportedDevices
7+ 
8+torch.npu.config.allow_internal_format = True
9+ 
10+# ACL format constants
11+ACL_FORMAT_ND = 2
12+ACL_FORMAT_FRACTAL_NZ = 29
13+ 
14+ 
15+class TestNpuFormatCastAclnn(TestCase):
16+ """
17+ Verify npu_format_cast aclnn implementation for ND -> FRACTAL_NZ.
18+ 
19+ Test groups:
20+ 1. ND -> NZ: format ID and data correctness
21+ 2. Inplace API (npu_format_cast_)
22+ 3. Tensor overload (npu_format_cast(src, dst_tensor))
23+ 4. Same-format no-op
24+ 5. Autograd / backward (requires_grad propagation)
25+ 6. Error cases
26+ """
27+ 
28+ # ------------------------------------------------------------------ #
29+ # Group 1: ND -> NZ format conversion
30+ # ------------------------------------------------------------------ #
31+ 
32+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
33+ def test_nd_to_nz_format_id_fp16(self):
34+ t = torch.rand(8, 16).half().npu()
35+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
36+ self.assertEqual(torch_npu.get_npu_format(out), ACL_FORMAT_FRACTAL_NZ)
37+ 
38+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
39+ def test_nd_to_nz_format_id_bf16(self):
40+ t = torch.rand(32, 64).bfloat16().npu()
41+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
42+ self.assertEqual(torch_npu.get_npu_format(out), ACL_FORMAT_FRACTAL_NZ)
43+ 
44+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
45+ def test_nd_to_nz_format_id_float32(self):
46+ t = torch.rand(16, 32).float().npu()
47+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
48+ self.assertEqual(torch_npu.get_npu_format(out), ACL_FORMAT_FRACTAL_NZ)
49+ 
50+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
51+ def test_nd_to_nz_shape_preserved_fp16(self):
52+ t = torch.rand(64, 128).half().npu()
53+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
54+ self.assertEqual(out.shape, t.shape)
55+ 
56+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
57+ def test_nd_to_nz_non_aligned_shape(self):
58+ t = torch.rand(15, 17).half().npu()
59+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
60+ self.assertEqual(torch_npu.get_npu_format(out), ACL_FORMAT_FRACTAL_NZ)
61+ self.assertEqual(out.shape, t.shape)
62+ 
63+ # ------------------------------------------------------------------ #
64+ # Group 1b: NZ -> ND format conversion (reverse)
65+ # ------------------------------------------------------------------ #
66+ 
67+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
68+ def test_nz_to_nd_format_id_fp16(self):
69+ """NZ -> ND: format changes back to ND."""
70+ t = torch.rand(8, 16).half().npu()
71+ nz = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
72+ back = torch_npu.npu_format_cast(nz, ACL_FORMAT_ND)
73+ self.assertEqual(torch_npu.get_npu_format(back), ACL_FORMAT_ND)
74+ 
75+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
76+ def test_nz_to_nd_format_id_bf16(self):
77+ """NZ -> ND bf16."""
78+ t = torch.rand(32, 64).bfloat16().npu()
79+ nz = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
80+ back = torch_npu.npu_format_cast(nz, ACL_FORMAT_ND)
81+ self.assertEqual(torch_npu.get_npu_format(back), ACL_FORMAT_ND)
82+ 
83+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
84+ def test_nz_to_nd_format_id_float32(self):
85+ """NZ -> ND float32."""
86+ t = torch.rand(16, 32).float().npu()
87+ nz = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
88+ back = torch_npu.npu_format_cast(nz, ACL_FORMAT_ND)
89+ self.assertEqual(torch_npu.get_npu_format(back), ACL_FORMAT_ND)
90+ 
91+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
92+ def test_nz_to_nd_shape_preserved(self):
93+ """NZ -> ND: logical shape unchanged."""
94+ t = torch.rand(64, 128).half().npu()
95+ nz = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
96+ back = torch_npu.npu_format_cast(nz, ACL_FORMAT_ND)
97+ self.assertEqual(back.shape, (64, 128))
98+ 
99+ # ------------------------------------------------------------------ #
100+ # Group 2: Inplace API (npu_format_cast_)
101+ # ------------------------------------------------------------------ #
102+ 
103+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
104+ def test_inplace_nd_to_nz_format_id(self):
105+ t = torch.rand(16, 32).half().npu()
106+ torch_npu.npu_format_cast_(t, ACL_FORMAT_FRACTAL_NZ)
107+ self.assertEqual(torch_npu.get_npu_format(t), ACL_FORMAT_FRACTAL_NZ)
108+ 
109+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
110+ def test_inplace_nz_to_nd_format_id(self):
111+ """Inplace NZ -> ND: format changes back."""
112+ t = torch.rand(15, 17).half().npu()
113+ torch_npu.npu_format_cast_(t, ACL_FORMAT_FRACTAL_NZ)
114+ torch_npu.npu_format_cast_(t, ACL_FORMAT_ND)
115+ self.assertEqual(torch_npu.get_npu_format(t), ACL_FORMAT_ND)
116+ 
117+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
118+ def test_inplace_roundtrip_data(self):
119+ """Inplace ND -> NZ -> ND: data preserved."""
120+ t = torch.rand(15, 17).half().npu()
121+ expected = t.cpu().clone()
122+ torch_npu.npu_format_cast_(t, ACL_FORMAT_FRACTAL_NZ)
123+ torch_npu.npu_format_cast_(t, ACL_FORMAT_ND)
124+ self.assertEqual(t.cpu(), expected)
125+ 
126+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
127+ def test_inplace_same_format_noop(self):
128+ """Inplace to same format: storage unchanged."""
129+ t = torch.rand(8, 16).half().npu()
130+ ptr_before = t.storage().data_ptr()
131+ torch_npu.npu_format_cast_(t, ACL_FORMAT_ND)
132+ self.assertEqual(t.storage().data_ptr(), ptr_before)
133+ 
134+ # ------------------------------------------------------------------ #
135+ # Group 3: Tensor overload npu_format_cast(src, dst_tensor)
136+ # ------------------------------------------------------------------ #
137+ 
138+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
139+ def test_tensor_overload_adopts_dst_format(self):
140+ """npu_format_cast(src, dst) converts src to dst's format."""
141+ src = torch.rand(8, 16).half().npu()
142+ dst_ref = torch_npu.npu_format_cast(torch.rand(8, 16).half().npu(), ACL_FORMAT_FRACTAL_NZ)
143+ result = torch_npu.npu_format_cast(src, dst_ref)
144+ self.assertEqual(torch_npu.get_npu_format(result), ACL_FORMAT_FRACTAL_NZ)
145+ 
146+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
147+ def test_tensor_overload_roundtrip_data(self):
148+ """npu_format_cast(src, dst) round-trip: data preserved."""
149+ src = torch.rand(15, 17).half().npu()
150+ expected = src.cpu().clone()
151+ nz_ref = torch_npu.npu_format_cast(torch.rand(15, 17).half().npu(), ACL_FORMAT_FRACTAL_NZ)
152+ nd_ref = torch.rand(15, 17).half().npu()
153+ nz = torch_npu.npu_format_cast(src, nz_ref)
154+ back = torch_npu.npu_format_cast(nz, nd_ref)
155+ self.assertEqual(back.cpu(), expected)
156+ 
157+ # ------------------------------------------------------------------ #
158+ # Group 4: Same-format no-op
159+ # ------------------------------------------------------------------ #
160+ 
161+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
162+ def test_same_format_nd_noop(self):
163+ """ND -> ND: same storage returned."""
164+ t = torch.rand(4, 8).half().npu()
165+ ptr_before = t.storage().data_ptr()
166+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_ND)
167+ self.assertEqual(out.storage().data_ptr(), ptr_before)
168+ 
169+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
170+ def test_same_format_nz_noop(self):
171+ """NZ -> NZ: same storage returned."""
172+ t = torch_npu.npu_format_cast(torch.rand(8, 16).half().npu(), ACL_FORMAT_FRACTAL_NZ)
173+ ptr_before = t.storage().data_ptr()
174+ out = torch_npu.npu_format_cast(t, ACL_FORMAT_FRACTAL_NZ)
175+ self.assertEqual(out.storage().data_ptr(), ptr_before)
176+ 
177+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
178+ def test_same_format_get_format_consistent(self):
179+ """After same-format cast, get_npu_format unchanged."""
180+ t = torch.rand(8, 16).half().npu()
181+ fmt = torch_npu.get_npu_format(t)
182+ out = torch_npu.npu_format_cast(t, fmt)
183+ self.assertEqual(torch_npu.get_npu_format(out), fmt)
184+ 
185+ # ------------------------------------------------------------------ #
186+ # Group 5: Autograd / backward
187+ # ------------------------------------------------------------------ #
188+ 
189+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
190+ def test_backward_requires_grad_preserved(self):
191+ """requires_grad propagates through format cast."""
192+ a = torch.rand(4, 8).half().npu().requires_grad_(True)
193+ b = torch_npu.npu_format_cast(a, ACL_FORMAT_FRACTAL_NZ)
194+ self.assertTrue(b.requires_grad)
195+ 
196+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
197+ def test_backward_same_format_noop(self):
198+ """Same-format cast (no-op path) also supports backward."""
199+ a = torch.rand(4, 8).float().npu().requires_grad_(True)
200+ ori_fmt = torch_npu.get_npu_format(a)
201+ b = torch_npu.npu_format_cast(a, ori_fmt)
202+ b.sum().backward()
203+ self.assertIsNotNone(a.grad)
204+ 
205+ # ------------------------------------------------------------------ #
206+ # Group 6: Error cases
207+ # ------------------------------------------------------------------ #
208+ 
209+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
210+ def test_noncontiguous_with_internal_format_raises(self):
211+ """Non-contiguous tensor with internal format raises RuntimeError."""
212+ nz = torch_npu.npu_format_cast(torch.rand(16, 32).half().npu(), ACL_FORMAT_FRACTAL_NZ)
213+ nz_t = nz.transpose(0, 1)
214+ with self.assertRaises(RuntimeError):
215+ torch_npu.npu_format_cast(nz_t, ACL_FORMAT_ND)
216+ 
217+ 
218+class TestNpuFormatCastDtypeParam(TestCase):
219+ """
220+ Tests for npu_format_cast with customize_dtype parameter.
221+ Default C0=16; customize_dtype=INT32 overrides to C0=8.
222+ """
223+ 
224+ ACL_FORMAT_ND = 2
225+ ACL_FORMAT_FRACTAL_NZ = 29
226+ 
227+ # dtype enum values (matching npu_native_functions.yaml / aclDataType)
228+ DTYPE_INT32 = 3
229+ 
230+ def _expected_nz_storage_bytes(self, shape, c0, element_size):
231+ m = shape[-2]
232+ n = shape[-1]
233+ batch = int(np.prod(shape[:-2])) if len(shape) > 2 else 1
234+ return batch * ((n + c0 - 1) // c0) * ((m + 15) // 16) * 16 * c0 * element_size
235+ 
236+ # ------------------------------------------------------------------ #
237+ # Baseline: fp16/float32 default to C0=16; int8 defaults to C0=32.
238+ # ------------------------------------------------------------------ #
239+ 
240+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
241+ def test_npu_format_cast_fp16_nd_to_nz(self):
242+ """fp16 ND -> NZ, default C0=16."""
243+ t = torch.rand(16, 32).half().npu()
244+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
245+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
246+ self.assertEqual(out.shape, t.shape)
247+ 
248+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
249+ def test_npu_format_cast_float32_nd_to_nz(self):
250+ """float32 ND -> NZ, default C0=16."""
251+ t = torch.rand(16, 32).float().npu()
252+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
253+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
254+ self.assertEqual(out.shape, t.shape)
255+ 
256+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
257+ def test_npu_format_cast_int8_nd_to_nz(self):
258+ """int8 ND -> NZ, default C0=32."""
259+ t = torch.randint(-128, 127, (32, 64), dtype=torch.int8).npu()
260+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
261+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
262+ self.assertEqual(out.shape, t.shape)
263+ 
264+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
265+ def test_npu_format_cast_int8_non_aligned(self):
266+ """int8 non-aligned shape, default C0=32."""
267+ t = torch.randint(-128, 127, (15, 17), dtype=torch.int8).npu()
268+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
269+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
270+ self.assertEqual(out.shape, t.shape)
271+ 
272+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
273+ def test_npu_format_cast_fp16_default_c0_16_storage_size(self):
274+ """fp16 non-aligned shape uses default C0=16."""
275+ shape = (15, 17)
276+ t = torch.rand(*shape).half().npu()
277+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
278+ self.assertEqual(out.untyped_storage().size(),
279+ self._expected_nz_storage_bytes(shape, 16, 2))
280+ 
281+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
282+ def test_npu_format_cast_int8_default_c0_32_storage_size(self):
283+ """int8 non-aligned shape uses default C0=32 in infer shape."""
284+ shape = (15, 33)
285+ t = torch.randint(-128, 127, shape, dtype=torch.int8).npu()
286+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
287+ self.assertEqual(out.untyped_storage().size(),
288+ self._expected_nz_storage_bytes(shape, 32, 1))
289+ 
290+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
291+ def test_npu_format_cast_int8_default_c0_32_storage_size_3d(self):
292+ """3D int8 infer shape preserves batch dims and uses C0=32."""
293+ shape = (3, 15, 33)
294+ t = torch.randint(-128, 127, shape, dtype=torch.int8).npu()
295+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
296+ self.assertEqual(out.untyped_storage().size(),
297+ self._expected_nz_storage_bytes(shape, 32, 1))
298+ 
299+ # ------------------------------------------------------------------ #
300+ # int32 with customize_dtype=INT32 to override default C0=16 to C0=8:
301+ # Without customize_dtype, 4-bit types default to C0=16 (FORMAT_REAL_TO_FAKE).
302+ # Explicitly passing customize_dtype=INT32 bypasses that and uses C0=8.
303+ # (910B only: 950 does not support customize_dtype)
304+ # ------------------------------------------------------------------ #
305+ 
306+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
307+ def test_npu_format_cast_int32_customize_dtype_nd_to_nz(self):
308+ """int32 with explicit customize_dtype=INT32: C0=8 ND -> FRACTAL_NZ."""
309+ t = torch.randint(0, 100, (32, 32), dtype=torch.int32).npu()
310+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
311+ customize_dtype=self.DTYPE_INT32)
312+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
313+ self.assertEqual(out.shape, t.shape)
314+ 
315+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
316+ def test_npu_format_cast_int32_customize_dtype_non_aligned(self):
317+ """int32 with explicit customize_dtype=INT32: C0=8 non-aligned shape."""
318+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
319+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
320+ customize_dtype=self.DTYPE_INT32)
321+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
322+ self.assertEqual(out.shape, t.shape)
323+ 
324+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
325+ def test_npu_format_cast_int32_customize_dtype_3d(self):
326+ """int32 with explicit customize_dtype=INT32: C0=8 3D shape."""
327+ t = torch.randint(0, 100, (4, 16, 32), dtype=torch.int32).npu()
328+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
329+ customize_dtype=self.DTYPE_INT32)
330+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
331+ self.assertEqual(out.shape, t.shape)
332+ 
333+ # ------------------------------------------------------------------ #
334+ # Storage size verification: explicitly verify C0 via storage bytes.
335+ # FRACTAL_NZ storage shape = (ceil(N/C0), ceil(M/16), 16, C0)
336+ # Different C0 values produce different storage sizes for non-aligned shapes.
337+ # ------------------------------------------------------------------ #
338+ 
339+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
340+ def test_npu_format_cast_c0_8_storage_size_2d(self):
341+ """Verify C0=8 storage size for (15, 17) int32.
342+ 
343+ FRACTAL_NZ with C0=8: (ceil(17/8), ceil(15/16), 16, 8) = (3,1,16,8)
344+ = 384 elements * 4 bytes = 1536 bytes.
345+ """
346+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
347+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
348+ customize_dtype=self.DTYPE_INT32)
349+ # C0=8: ceil(17/8)*ceil(15/16)*16*8 * 4bytes = 3*1*128 * 4 = 1536
350+ expected_bytes = self._expected_nz_storage_bytes((15, 17), 8, 4)
351+ self.assertEqual(out.untyped_storage().size(), expected_bytes)
352+ 
353+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
354+ def test_npu_format_cast_c0_8_vs_default_c0_16_storage_differs(self):
355+ """C0=8 (customize_dtype=INT32) vs default C0=16 produce different storage.
356+ 
357+ For (15, 17) int32:
358+ Default C0=16: (ceil(17/16), ceil(15/16), 16, 16) = 512 elements * 4 = 2048 bytes
359+ customize_dtype=INT32 C0=8: (ceil(17/8), ceil(15/16), 16, 8) = 384 elements * 4 = 1536 bytes
360+ """
361+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
362+ out_default = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
363+ out_c0_8 = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
364+ customize_dtype=self.DTYPE_INT32)
365+ # Default C0=16 should be larger than C0=8
366+ self.assertGreater(out_default.untyped_storage().size(),
367+ out_c0_8.untyped_storage().size())
368+ 
369+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
370+ def test_npu_format_cast_default_c0_16_storage_size(self):
371+ """Verify default C0=16 storage size for (15, 17) int32 without customize_dtype.
372+ 
373+ Default C0=16: (ceil(17/16), ceil(15/16), 16, 16) = (2,1,16,16)
374+ = 512 elements * 4 bytes = 2048 bytes.
375+ """
376+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
377+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
378+ # Default C0=16: ceil(17/16)*ceil(15/16)*16*16 * 4bytes = 2*1*256*4 = 2048
379+ expected_bytes = self._expected_nz_storage_bytes((15, 17), 16, 4)
380+ self.assertEqual(out.untyped_storage().size(), expected_bytes)
381+ 
382+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
383+ def test_npu_format_cast_c0_8_storage_size_3d(self):
384+ """Verify C0=8 storage size for 3D (4, 15, 17) int32.
385+ 
386+ 3D FRACTAL_NZ: batch dims preserved, last 2 dims follow NZ layout.
387+ C0=8: 4 * ceil(17/8) * ceil(15/16) * 16 * 8 = 4*3*1*16*8 = 1536 elements * 4 = 6144 bytes.
388+ """
389+ t = torch.randint(0, 100, (4, 15, 17), dtype=torch.int32).npu()
390+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
391+ customize_dtype=self.DTYPE_INT32)
392+ # 4 * ceil(17/8) * ceil(15/16) * 16 * 8 * 4bytes = 4*3*1*128*4 = 6144
393+ expected_bytes = self._expected_nz_storage_bytes((4, 15, 17), 8, 4)
394+ self.assertEqual(out.untyped_storage().size(), expected_bytes)
7 395 
8 396 
9class TestFormatCast(TestCase):397class TestFormatCast(TestCase):
398+ ACL_FORMAT_ND = 2
399+ ACL_FORMAT_FRACTAL_NZ = 29
400+ 
401+ # ------------------------------------------------------------------ #
402+ # 2D: ND -> FRACTAL_NZ
403+ # ------------------------------------------------------------------ #
404+ 
405+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
406+ def test_2d_nd_to_nz_format_id(self):
407+ """2D fp16 ND -> FRACTAL_NZ format ID."""
408+ t = torch.rand(16, 32).half().npu()
409+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
410+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
411+ self.assertEqual(out.shape, t.shape)
412+ 
413+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
414+ def test_2d_nd_to_nz_bf16(self):
415+ """2D bf16 ND -> FRACTAL_NZ."""
416+ t = torch.rand(16, 32).bfloat16().npu()
417+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
418+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
419+ self.assertEqual(out.shape, t.shape)
420+ 
421+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
422+ def test_2d_nd_to_nz_int8(self):
423+ """2D int8 ND -> FRACTAL_NZ."""
424+ t = torch.randint(-128, 127, (32, 64), dtype=torch.int8).npu()
425+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
426+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
427+ self.assertEqual(out.shape, t.shape)
428+ 
429+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
430+ def test_2d_nd_to_nz_large_shape(self):
431+ """2D large shape ND -> FRACTAL_NZ."""
432+ t = torch.rand(256, 512).half().npu()
433+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
434+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
435+ self.assertEqual(out.shape, t.shape)
436+ 
437+ # ------------------------------------------------------------------ #
438+ # 3D: ND -> FRACTAL_NZ
439+ # ------------------------------------------------------------------ #
440+ 
441+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
442+ def test_3d_nd_to_nz_format_id(self):
443+ """3D fp16 ND -> FRACTAL_NZ format ID."""
444+ t = torch.rand(4, 16, 32).half().npu()
445+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
446+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
447+ self.assertEqual(out.shape, t.shape)
448+ 
449+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
450+ def test_3d_nd_to_nz_non_aligned(self):
451+ """3D non-aligned shape ND -> FRACTAL_NZ."""
452+ t = torch.rand(3, 15, 17).half().npu()
453+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
454+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
455+ self.assertEqual(out.shape, t.shape)
456+ 
457+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
458+ def test_3d_nd_to_nz_bf16(self):
459+ """3D bf16 ND -> FRACTAL_NZ."""
460+ t = torch.rand(2, 16, 32).bfloat16().npu()
461+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
462+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
463+ self.assertEqual(out.shape, t.shape)
464+ 
465+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
466+ def test_3d_nd_to_nz_float32(self):
467+ """3D float32 ND -> FRACTAL_NZ."""
468+ t = torch.rand(2, 16, 32).float().npu()
469+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
470+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
471+ self.assertEqual(out.shape, t.shape)
472+ 
473+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
474+ def test_3d_nd_to_nz_int8(self):
475+ """3D int8 ND -> FRACTAL_NZ."""
476+ t = torch.randint(-128, 127, (4, 16, 32), dtype=torch.int8).npu()
477+ out = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
478+ self.assertEqual(torch_npu.get_npu_format(out), self.ACL_FORMAT_FRACTAL_NZ)
479+ self.assertEqual(out.shape, t.shape)
480+ 
481+ 
482+class TestNpuFormatCastPrecision(TestCase):
483+ """
484+ Precision tests for npu_format_cast via round-trip verification.
485+ 
486+ ND -> FRACTAL_NZ -> ND: compare round-trip result against original data.
487+ (Direct storage comparison is not possible because untyped_storage().copy_()
488+ triggers internal TransData which fails on current CANN versions.)
489+ """
490+ 
491+ def setUp(self):
492+ try:
493+ torch.npu.synchronize()
494+ except RuntimeError:
495+ pass
496+ 
497+ ACL_FORMAT_ND = 2
498+ ACL_FORMAT_FRACTAL_NZ = 29
499+ 
500+ DTYPE_INT32 = 3
501+ 
502+ def _verify_roundtrip_nz(self, t_npu):
503+ """ND -> NZ -> ND round-trip, compare with original.
504+ 
505+ Note: save expected data BEFORE format_cast because aclnnNpuFormatCast
506+ may corrupt the source tensor's buffer (CANN receives a non-const pointer
507+ via const_cast in ConvertType and writes to it during conversion).
508+ """
509+ expected = t_npu.cpu().clone()
510+ nz = torch_npu.npu_format_cast(t_npu, self.ACL_FORMAT_FRACTAL_NZ)
511+ back = torch_npu.npu_format_cast(nz, self.ACL_FORMAT_ND)
512+ self.assertEqual(torch_npu.get_npu_format(back), self.ACL_FORMAT_ND)
513+ self.assertEqual(back.shape, t_npu.shape)
514+ self.assertEqual(back.cpu(), expected)
515+ 
516+ # ------------------------------------------------------------------ #
517+ # fp16 round-trip
518+ # ------------------------------------------------------------------ #
519+ 
520+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
521+ def test_roundtrip_nz_fp16_2d_aligned(self):
522+ t = torch.rand(16, 32).half().npu()
523+ self._verify_roundtrip_nz(t)
524+ 
525+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
526+ def test_roundtrip_nz_fp16_2d_non_aligned(self):
527+ t = torch.rand(15, 17).half().npu()
528+ self._verify_roundtrip_nz(t)
529+ 
530+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
531+ def test_roundtrip_nz_fp16_3d(self):
532+ t = torch.rand(4, 16, 32).half().npu()
533+ self._verify_roundtrip_nz(t)
534+ 
535+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
536+ def test_roundtrip_nz_fp16_3d_non_aligned(self):
537+ t = torch.rand(3, 15, 17).half().npu()
538+ self._verify_roundtrip_nz(t)
539+ 
540+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
541+ def test_roundtrip_nz_fp16_large(self):
542+ t = torch.rand(256, 512).half().npu()
543+ self._verify_roundtrip_nz(t)
544+ 
545+ # ------------------------------------------------------------------ #
546+ # bf16 round-trip
547+ # ------------------------------------------------------------------ #
548+ 
549+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
550+ def test_roundtrip_nz_bf16_2d(self):
551+ t = torch.rand(16, 32).bfloat16().npu()
552+ self._verify_roundtrip_nz(t)
553+ 
554+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
555+ def test_roundtrip_nz_bf16_2d_non_aligned(self):
556+ t = torch.rand(15, 17).bfloat16().npu()
557+ self._verify_roundtrip_nz(t)
558+ 
559+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
560+ def test_roundtrip_nz_bf16_3d(self):
561+ t = torch.rand(3, 15, 17).bfloat16().npu()
562+ self._verify_roundtrip_nz(t)
563+ 
564+ # ------------------------------------------------------------------ #
565+ # float32 round-trip
566+ # ------------------------------------------------------------------ #
567+ 
568+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
569+ def test_roundtrip_nz_float32_2d(self):
570+ t = torch.rand(16, 32).float().npu()
571+ self._verify_roundtrip_nz(t)
572+ 
573+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
574+ def test_roundtrip_nz_float32_3d(self):
575+ t = torch.rand(2, 16, 32).float().npu()
576+ self._verify_roundtrip_nz(t)
577+ 
578+ # ------------------------------------------------------------------ #
579+ # int8 round-trip
580+ # ------------------------------------------------------------------ #
581+ 
582+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
583+ def test_roundtrip_nz_int8_2d(self):
584+ t = torch.randint(-128, 127, (32, 64), dtype=torch.int8).npu()
585+ self._verify_roundtrip_nz(t)
586+ 
587+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
588+ def test_roundtrip_nz_int8_2d_non_aligned(self):
589+ t = torch.randint(-128, 127, (15, 17), dtype=torch.int8).npu()
590+ self._verify_roundtrip_nz(t)
591+ 
592+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
593+ def test_roundtrip_nz_int8_3d(self):
594+ t = torch.randint(-128, 127, (4, 16, 32), dtype=torch.int8).npu()
595+ self._verify_roundtrip_nz(t)
596+ 
597+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
598+ def test_roundtrip_nz_int8_3d_non_aligned(self):
599+ t = torch.randint(-128, 127, (3, 15, 17), dtype=torch.int8).npu()
600+ self._verify_roundtrip_nz(t)
601+ 
602+ @SupportedDevices(['Ascend910B', 'Ascend910_93', 'Ascend950'])
603+ def test_roundtrip_nz_reverse_direction_uses_format_sensitive_cache(self):
604+ t = torch.arange(16 * 32, dtype=torch.float16).reshape(16, 32).npu()
605+ self._verify_roundtrip_nz(t)
606+ 
607+ # ------------------------------------------------------------------ #
608+ # int32 default C0=16 round-trip
609+ # ------------------------------------------------------------------ #
610+ 
611+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
612+ def test_roundtrip_nz_int32_default_c0_16(self):
613+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
614+ expected = t.cpu().clone()
615+ nz = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ)
616+ back = torch_npu.npu_format_cast(nz, self.ACL_FORMAT_ND)
617+ self.assertEqual(back.cpu(), expected)
618+ 
619+ # ------------------------------------------------------------------ #
620+ # int32 with customize_dtype=INT32 (C0=8) round-trip on 910B
621+ # ------------------------------------------------------------------ #
622+ 
623+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
624+ def test_roundtrip_nz_int32_c0_8_aligned(self):
625+ t = torch.randint(0, 100, (16, 8), dtype=torch.int32).npu()
626+ expected = t.cpu().clone()
627+ nz = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
628+ customize_dtype=self.DTYPE_INT32)
629+ back = torch_npu.npu_format_cast(nz, self.ACL_FORMAT_ND)
630+ self.assertEqual(back.cpu(), expected)
631+ 
632+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
633+ def test_roundtrip_nz_int32_c0_8_non_aligned(self):
634+ t = torch.randint(0, 100, (15, 17), dtype=torch.int32).npu()
635+ expected = t.cpu().clone()
636+ nz = torch_npu.npu_format_cast(t, self.ACL_FORMAT_FRACTAL_NZ,
637+ customize_dtype=self.DTYPE_INT32)
638+ back = torch_npu.npu_format_cast(nz, self.ACL_FORMAT_ND)
639+ self.assertEqual(back.cpu(), expected)
640+ 
641+ 
642+class TestZFormatCastOriginal(TestCase):
643+ ACL_FORMAT_NC1HWC0 = 3
10 644 
11 def supported_op_exec(self, input1):645 def supported_op_exec(self, input1):
12 m = torch.nn.Identity(54, unused_argument1=0.1, unused_argument2=False)646 m = torch.nn.Identity(54, unused_argument1=0.1, unused_argument2=False)
@@ -17,13 +651,15 @@ class TestFormatCast(TestCase):
17 output = torch_npu.npu_format_cast(input1, acl_format)651 output = torch_npu.npu_format_cast(input1, acl_format)
18 return output.cpu().detach()652 return output.cpu().detach()
19 653 
654+ # Ascend950 does not support this 4D NC1HWC0 format_cast case.
655+ @SupportedDevices(['Ascend910B', 'Ascend910_93'])
20 def test_npu_format_cast(self, device="npu"):656 def test_npu_format_cast(self, device="npu"):
657+ """Original test: NCHW -> NC1HWC0 data correctness."""
21 item = [np.float16, 0, (2, 2, 4, 4)]658 item = [np.float16, 0, (2, 2, 4, 4)]
22 _, npu_input = create_common_tensor(item, -1, 1)659 _, npu_input = create_common_tensor(item, -1, 1)
23- acl_format = 3
24 660 
25 supported_output = self.supported_op_exec(npu_input)661 supported_output = self.supported_op_exec(npu_input)
26- custom_output = self.custom_op_exec(npu_input, acl_format)662+ custom_output = self.custom_op_exec(npu_input, self.ACL_FORMAT_NC1HWC0)
27 self.assertRtolEqual(supported_output, custom_output)663 self.assertRtolEqual(supported_output, custom_output)
28 664 
29 665 
@@ -1 +1 @@
1-Subproject commit d9c8fb04f4dfed684940182add0634bd5cbef7f71+Subproject commit 1ddd4d0aec25f1dfd4a85f66a93793a6097abcf6
C
Cchengpeng256月11日

不需要手动刷新op-plugin的commit-id

likedislike
@@ -7,6 +7,7 @@
7#include "torch_npu/csrc/core/NPUBridge.h"7#include "torch_npu/csrc/core/NPUBridge.h"
8#include "torch_npu/csrc/core/NPUStorageImpl.h"8#include "torch_npu/csrc/core/NPUStorageImpl.h"
9#include "torch_npu/csrc/core/npu/NpuVariables.h"9#include "torch_npu/csrc/core/npu/NpuVariables.h"
10+#include "torch_npu/csrc/core/npu/GetCANNInfo.h"
10#include "torch_npu/csrc/aten/CustomFunctions.h"11#include "torch_npu/csrc/aten/CustomFunctions.h"
11#include "torch_npu/csrc/custom_dtype/Init.h"12#include "torch_npu/csrc/custom_dtype/Init.h"
12#include "third_party/op-plugin/op_plugin/utils/op_api_common.h"13#include "third_party/op-plugin/op_plugin/utils/op_api_common.h"
@@ -22,6 +23,38 @@ static std::unordered_map<int, int> FORMAT_REAL_TO_FAKE {
22using tensor_list = std::vector<at::Tensor>;23using tensor_list = std::vector<at::Tensor>;
23using GetFormatFunc = int (*)(const aclTensor *, const int, const int, int64_t **, uint64_t *, int *);24using GetFormatFunc = int (*)(const aclTensor *, const int, const int, int64_t **, uint64_t *, int *);
24 25 
26+// Check if current CANN version supports aclnn format_cast with customize_dtype.
27+// Only 910B and 910C series support aclnnNpuFormatCastCalculateSizeAndFormat.
28+// 950 goes through IsAclnnOnly() path separately; 910A/310 series do not support this API.
29+static bool IsAclnnFormatCastSupported()
30+{
31+ static const auto soc = c10_npu::GetSocVersion();
32+ static const bool supported = IsGteCANNVersion("9.1.0", "CANN") &&
33+ ((soc >= c10_npu::SocVersion::Ascend910B1 && soc < c10_npu::SocVersion::Ascend310B1) ||
34+ (soc >= c10_npu::SocVersion::Ascend910_9391 && soc < c10_npu::SocVersion::Ascend950));
35+ return supported;
36+}
37+ 
38+static bool ShouldFallbackNzToNd(const at::Tensor& self, int64_t acl_format)
39+{
40+ if (acl_format != ACL_FORMAT_FRACTAL_NZ) {
41+ return false;
42+ }
43+ auto src_desc = torch_npu::NPUBridge::GetNpuStorageImpl(self)->npu_desc_;
44+ if (src_desc.npu_format_ != ACL_FORMAT_ND) {
45+ return false;
46+ }
47+ if (src_desc.base_sizes_.size() != self.sizes().size()) {
48+ return true;
49+ }
50+ for (size_t i = 0; i < src_desc.base_sizes_.size(); ++i) {
51+ if (src_desc.base_sizes_[i] != self.sizes()[i]) {
52+ return true;
53+ }
54+ }
55+ return false;
56+}
57+ 
25std::tuple<bool, int64_t, c10::SmallVector<int64_t, SIZE>> MaybeUseAclnnNpuFormatCast(const at::Tensor& src,58std::tuple<bool, int64_t, c10::SmallVector<int64_t, SIZE>> MaybeUseAclnnNpuFormatCast(const at::Tensor& src,
26 int64_t acl_format, c10::optional<int64_t> customize_dtype, c10::optional<int64_t> input_dtype)59 int64_t acl_format, c10::optional<int64_t> customize_dtype, c10::optional<int64_t> input_dtype)
27{60{
@@ -71,6 +104,51 @@ std::tuple<bool, int64_t, c10::SmallVector<int64_t, SIZE>> MaybeUseAclnnNpuForma
71 "aclnnNpuFormatCast does not exist, Current soc version only support aclnn operators.",104 "aclnnNpuFormatCast does not exist, Current soc version only support aclnn operators.",
72 PTA_ERROR(ErrCode::NOT_SUPPORT));105 PTA_ERROR(ErrCode::NOT_SUPPORT));
73 }106 }
107+ // Non-aclnn-only path (910B and older chips).
108+ // CANN >= 9.1.0 supports aclnn format_cast with customize_dtype on 910B.
109+ // Match original aclop behavior: 4-byte types (float32/int32) default to
110+ // ACL_FLOAT16 (C0=16); smaller types keep their natural C0 (int8→32, fp16→16).
111+ // See FormatHelper.cpp InferShapeNDToNZ: (itemsize > 2) ? 2 : itemsize.
112+ if (!customize_dtype.has_value()) {
113+ if (src.element_size() >= 4) {
114+ customizeAcltype = aclDataType::ACL_FLOAT16;
115+ }
116+ }
117+ // else: customizeAcltype stays as user's customize_dtype value (set at top of function)
118+ if (IsAclnnFormatCastSupported() && aclnnNpuFormatCastExist) {
119+ auto acl_src = ConvertType(srcWrapper);
120+ auto api_ret = GetFormat(acl_src, acl_format, customizeAcltype, &dstStorageShape,
121+ &dstShapeSize, &dstFormat);
122+ Release(acl_src);
123+ // CANN aclnn does not yet support all format pairs (e.g. NC1HWC0->ND,
124+ // 2D->NC1HWC0, 4D->NZ). Fall back to aclop for unsupported pairs.
125+ if (api_ret != 0) {
126+ return std::make_tuple(false, dstFormat, outputShape);
127+ }
128+ for (uint64_t i = 0; i < dstShapeSize; i++) {
129+ outputShape.push_back(dstStorageShape[i]);
130+ }
131+ // For 4-bit types: when customize_dtype=INT32 (8 packed int4, C0=8),
132+ // CANN already computes correct storage shape, skip halving.
133+ // Otherwise default C0=16: halve last dim and remap format.
134+ if (customizeAcltype != aclDataType::ACL_INT32 &&
135+ (srcAcltype == aclDataType::ACL_FLOAT4_E2M1 || srcAcltype == aclDataType::ACL_FLOAT4_E1M2 ||
136+ srcAcltype == aclDataType::ACL_INT4)) {
137+ if (FORMAT_REAL_TO_FAKE.find(dstFormat) == FORMAT_REAL_TO_FAKE.end() || outputShape.empty()) {
138+ delete[] dstStorageShape;
139+ dstStorageShape = nullptr;
140+ TORCH_CHECK(false,
141+ "aclnnNpuFormatCast not support recovery format.",
142+ PTA_ERROR(ErrCode::NOT_SUPPORT));
143+ }
144+ outputShape.back() = outputShape.back() >> 1;
145+ dstFormat = FORMAT_REAL_TO_FAKE[dstFormat];
146+ }
147+ delete[] dstStorageShape;
148+ dstStorageShape = nullptr;
149+ return std::make_tuple(true, static_cast<int64_t>(dstFormat), outputShape);
150+ }
151+ // CANN < 9.1.0: customize_dtype not supported, fall back to aclop path.
74 if (C10_UNLIKELY(customize_dtype.has_value())) {152 if (C10_UNLIKELY(customize_dtype.has_value())) {
75 TORCH_CHECK(false,153 TORCH_CHECK(false,
76 "customize_dtype is not supported by the current soc version.",154 "customize_dtype is not supported by the current soc version.",
@@ -324,6 +402,11 @@ at::Tensor NPUNativeFunctions::npu_format_cast(const at::Tensor& self, int64_t a
324 c10::optional<int64_t> input_dtype)402 c10::optional<int64_t> input_dtype)
325{403{
326 torch_npu::utils::torch_check_npu(self);404 torch_npu::utils::torch_check_npu(self);
405+ // Match aclop behavior for manually set storage tensors whose NPU desc
406+ // base shape does not match current logical shape.
407+ if (ShouldFallbackNzToNd(self, acl_format)) {
408+ acl_format = ACL_FORMAT_ND;
C
Cchengpeng256月11日

acl_format回退ND,建议给出提示

likedislike
shawnylee233
6月11日 评论:
409+ }
327 if (NPUNativeFunctions::get_npu_format(self) == acl_format) {410 if (NPUNativeFunctions::get_npu_format(self) == acl_format) {
328 ASCEND_LOGD("no need to do format cast");411 ASCEND_LOGD("no need to do format cast");
329 return self;412 return self;