Merged
feat(zero_op): aclnnInplaceZero支持UINT32/UINT64数据类型 #7016
fitZepHYrAdd on 7 days ago
feat(zero_op): aclnnInplaceZero支持UINT32/UINT64数据类型 #7016
Merged
Total: 4 files changed+57-16
| @@ -124,7 +124,7 @@ aclnnStatus aclnnInplaceZero( | |||
| 124 | - <term>Atlas推理系列产品</term>、<term>Atlas训练系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64。 | 124 | - <term>Atlas推理系列产品</term>、<term>Atlas训练系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64。 |
| 125 | <!-- end id7 --> | 125 | <!-- end id7 --> |
| 126 | <!-- npu="A3,910b" id8 --> | 126 | <!-- npu="A3,910b" id8 --> |
| 127 | -- <term>Atlas A2系列产品</term>、<term>Atlas A3系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64、BFLOAT16。 | 127 | +- <term>Atlas A2系列产品</term>、<term>Atlas A3系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64、BFLOAT16、UINT32、UINT64。 |
| 128 | <!-- end id8 --> | 128 | <!-- end id8 --> |
| 129 | <!-- npu="950" id9 --> | 129 | <!-- npu="950" id9 --> |
| 130 | - <term>Ascend 950PR&950DT系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64、BFLOAT16、FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8、FLOAT4_E1M2、FLOAT4_E2M1。 | 130 | - <term>Ascend 950PR&950DT系列产品</term>:数据类型支持INT8、INT32、INT64、UINT8、FLOAT16、FLOAT32、BOOL、DOUBLE、INT16、UINT16、COMPLEX128、COMPLEX64、BFLOAT16、FLOAT8_E5M2、FLOAT8_E4M3FN、HIFLOAT8、FLOAT4_E1M2、FLOAT4_E2M1。 |
| @@ -126,7 +126,7 @@ aclnnStatus aclnnInplaceZero( | |||
| 126 | - <term>Atlas inference products</term>, <term>Atlas training products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64. | 126 | - <term>Atlas inference products</term>, <term>Atlas training products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64. |
| 127 | <!-- end id7 --> | 127 | <!-- end id7 --> |
| 128 | <!-- npu="A3,910b" id8 --> | 128 | <!-- npu="A3,910b" id8 --> |
| 129 | -- <term>Atlas A2 products</term>, <term>Atlas A3 products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64, BFLOAT16. | 129 | +- <term>Atlas A2 products</term>, <term>Atlas A3 products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64, BFLOAT16, UINT32, UINT64. |
| 130 | <!-- end id8 --> | 130 | <!-- end id8 --> |
| 131 | <!-- npu="950" id9 --> | 131 | <!-- npu="950" id9 --> |
| 132 | - <term>Ascend 950PR&950DT products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64, BFLOAT16, FLOAT8_E5M2, FLOAT8_E4M3FN, HIFLOAT8, FLOAT4_E1M2, FLOAT4_E2M1. | 132 | - <term>Ascend 950PR&950DT products</term>: Supports the following data types: INT8, INT32, INT64, UINT8, FLOAT16, FLOAT32, BOOL, DOUBLE, INT16, UINT16, COMPLEX128, COMPLEX64, BFLOAT16, FLOAT8_E5M2, FLOAT8_E4M3FN, HIFLOAT8, FLOAT4_E1M2, FLOAT4_E2M1. |
| @@ -38,7 +38,7 @@ static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST = { | |||
| 38 | op::DataType::DT_INT8, op::DataType::DT_INT32, op::DataType::DT_INT64, op::DataType::DT_UINT8, | 38 | op::DataType::DT_INT8, op::DataType::DT_INT32, op::DataType::DT_INT64, op::DataType::DT_UINT8, |
| 39 | op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_BOOL, op::DataType::DT_DOUBLE, | 39 | op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_BOOL, op::DataType::DT_DOUBLE, |
| 40 | op::DataType::DT_INT16, op::DataType::DT_UINT16, op::DataType::DT_COMPLEX128, op::DataType::DT_COMPLEX64, | 40 | op::DataType::DT_INT16, op::DataType::DT_UINT16, op::DataType::DT_COMPLEX128, op::DataType::DT_COMPLEX64, |
| 41 | - op::DataType::DT_BF16}; | 41 | + op::DataType::DT_BF16, op::DataType::DT_UINT32, op::DataType::DT_UINT64}; |
| 42 | 42 | ||
| 43 | static const std::initializer_list<op::DataType> DTYPE_SUPPORT_950_LIST = { | 43 | static const std::initializer_list<op::DataType> DTYPE_SUPPORT_950_LIST = { |
| 44 | op::DataType::DT_INT8, op::DataType::DT_INT32, op::DataType::DT_INT64, | 44 | op::DataType::DT_INT8, op::DataType::DT_INT32, op::DataType::DT_INT64, |
| @@ -88,6 +88,17 @@ static aclnnStatus CheckParams(const aclTensor* self) | |||
| 88 | return ACLNN_SUCCESS; | 88 | return ACLNN_SUCCESS; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | +static void ViewDataType(const aclTensor* input, const op::DataType dtype) | ||
| 92 | +{ | ||
| 93 | + if (input == nullptr) { | ||
| 94 | + OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "view failed: input tensor is null."); | ||
| 95 | + return; | ||
| 96 | + } | ||
| 97 | + auto tmpTensor = const_cast<aclTensor*>(input); | ||
| 98 | + tmpTensor->SetDataType(dtype); | ||
| 99 | + input = tmpTensor; | ||
| 100 | +} | ||
| 101 | + | ||
| 91 | aclnnStatus aclnnInplaceZeroGetWorkspaceSize(aclTensor* selfRef, uint64_t* workspaceSize, aclOpExecutor** executor) | 102 | aclnnStatus aclnnInplaceZeroGetWorkspaceSize(aclTensor* selfRef, uint64_t* workspaceSize, aclOpExecutor** executor) |
| 92 | { | 103 | { |
| 93 | L2_DFX_PHASE_1(aclnnInplaceZero, DFX_IN(selfRef), DFX_OUT(selfRef)); | 104 | L2_DFX_PHASE_1(aclnnInplaceZero, DFX_IN(selfRef), DFX_OUT(selfRef)); |
| @@ -96,7 +107,7 @@ aclnnStatus aclnnInplaceZeroGetWorkspaceSize(aclTensor* selfRef, uint64_t* works | |||
| 96 | auto uniqueExecutor = CREATE_EXECUTOR(); | 107 | auto uniqueExecutor = CREATE_EXECUTOR(); |
| 97 | CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | 108 | CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); |
| 98 | 109 | ||
| 99 | - // 固定写法,参数检查 | 110 | + // 固定写法,参数检查(包含空指针与dtype校验) |
| 100 | auto ret = CheckParams(selfRef); | 111 | auto ret = CheckParams(selfRef); |
| 101 | CHECK_RET(ret == ACLNN_SUCCESS, ret); | 112 | CHECK_RET(ret == ACLNN_SUCCESS, ret); |
| 102 | 113 | ||
| @@ -107,8 +118,18 @@ aclnnStatus aclnnInplaceZeroGetWorkspaceSize(aclTensor* selfRef, uint64_t* works | |||
| 107 | return ACLNN_SUCCESS; | 118 | return ACLNN_SUCCESS; |
| 108 | } | 119 | } |
| 109 | 120 | ||
| 121 | + // uint32/uint64 复用 int32/int64 的 ZerosLike 实现,通过视图修改类型,不改变入参 selfRef 本身 | ||
| 122 | + const aclTensor* self = selfRef; | ||
| 123 | + auto selfDtype = self->GetDataType(); | ||
| 124 | + if (selfDtype == op::DataType::DT_UINT64 || selfDtype == op::DataType::DT_UINT32) { | ||
| 125 | + self = uniqueExecutor->CreateView(selfRef, selfRef->GetViewShape(), selfRef->GetStorageShape(), | ||
| 126 | + selfRef->GetViewStrides(), selfRef->GetViewOffset()); | ||
| 127 | + CHECK_RET(self != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 128 | + ViewDataType(self, selfDtype == op::DataType::DT_UINT64 ? op::DataType::DT_INT64 : op::DataType::DT_INT32); | ||
| 129 | + } | ||
| 130 | + | ||
| 110 | // 固定写法,将输入self转换成连续的tensor | 131 | // 固定写法,将输入self转换成连续的tensor |
| 111 | - auto selfContiguous = l0op::Contiguous(selfRef, uniqueExecutor.get()); | 132 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); |
| 112 | CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | 133 | CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); |
| 113 | 134 | ||
| 114 | // 调用ZerosLike算子kernel | 135 | // 调用ZerosLike算子kernel |
| @@ -116,7 +137,9 @@ aclnnStatus aclnnInplaceZeroGetWorkspaceSize(aclTensor* selfRef, uint64_t* works | |||
| 116 | CHECK_RET(zeroOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | 137 | CHECK_RET(zeroOut != nullptr, ACLNN_ERR_INNER_NULLPTR); |
| 117 | 138 | ||
| 118 | // 固定写法,将计算结果拷贝到输出out上,out可能是非连续的tensor | 139 | // 固定写法,将计算结果拷贝到输出out上,out可能是非连续的tensor |
| 119 | - auto viewcopyResult = l0op::ViewCopy(zeroOut, selfRef, uniqueExecutor.get()); | 140 | + // 注意:self和selfRef指向同一个内存地址,self用int32/int64解析,selfRef用uint32/uint64解析 |
| 141 | + // 但计算结果zeroOut是int32/int64类型,需要通过ViewCopy拷贝到同为int32/int64的的self上 | ||
| 142 | + auto viewcopyResult = l0op::ViewCopy(zeroOut, self, uniqueExecutor.get()); | ||
Y | |||
| 120 | CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | 143 | CHECK_RET(viewcopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR); |
| 121 | 144 | ||
| 122 | // 固定写法,获取计算过程中需要使用的workspace大小 | 145 | // 固定写法,获取计算过程中需要使用的workspace大小 |
| @@ -15,21 +15,15 @@ | |||
| 15 | 15 | ||
| 16 | class l2ZeroTest : public testing::Test { | 16 | class l2ZeroTest : public testing::Test { |
| 17 | protected: | 17 | protected: |
| 18 | - static void SetUpTestCase() | 18 | + static void SetUpTestCase() { std::cout << "l2ZeroTest SetUp" << std::endl; } |
| 19 | - { | ||
| 20 | - std::cout << "l2ZeroTest SetUp" << std::endl; | ||
| 21 | - } | ||
| 22 | 19 | ||
| 23 | - static void TearDownTestCase() | 20 | + static void TearDownTestCase() { std::cout << "l2ZeroTest TearDown" << std::endl; } |
| 24 | - { | ||
| 25 | - std::cout << "l2ZeroTest TearDown" << std::endl; | ||
| 26 | - } | ||
| 27 | }; | 21 | }; |
| 28 | 22 | ||
| 29 | // self的数据类型不在支持范围内 | 23 | // self的数据类型不在支持范围内 |
| 30 | TEST_F(l2ZeroTest, l2_zero_test_unsupported_type) | 24 | TEST_F(l2ZeroTest, l2_zero_test_unsupported_type) |
| 31 | { | 25 | { |
| 32 | - auto selfDesc = TensorDesc({2, 3}, ACL_UINT32, ACL_FORMAT_ND); | 26 | + auto selfDesc = TensorDesc({2, 3}, ACL_COMPLEX32, ACL_FORMAT_ND); |
| 33 | 27 | ||
| 34 | auto ut = OP_API_UT(aclnnInplaceZero, INPUT(selfDesc), OUTPUT()); | 28 | auto ut = OP_API_UT(aclnnInplaceZero, INPUT(selfDesc), OUTPUT()); |
| 35 | 29 | ||
| @@ -89,6 +83,30 @@ TEST_F(l2ZeroTest, l2_zero_test_int64) | |||
| 89 | // ut.TestPrecision(); | 83 | // ut.TestPrecision(); |
| 90 | } | 84 | } |
| 91 | 85 | ||
| 86 | +// 正常路径, uint32 | ||
| 87 | +TEST_F(l2ZeroTest, l2_zero_test_uint32) | ||
| 88 | +{ | ||
| 89 | + auto selfDesc = TensorDesc({2, 4}, ACL_UINT32, ACL_FORMAT_ND); | ||
| 90 | + | ||
| 91 | + auto ut = OP_API_UT(aclnnInplaceZero, INPUT(selfDesc), OUTPUT()); | ||
| 92 | + | ||
| 93 | + uint64_t workspaceSize = 0; | ||
| 94 | + aclnnStatus getWorkspaceResult = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 95 | + EXPECT_EQ(getWorkspaceResult, ACLNN_SUCCESS); | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +// 正常路径, uint64 | ||
| 99 | +TEST_F(l2ZeroTest, l2_zero_test_uint64) | ||
| 100 | +{ | ||
| 101 | + auto selfDesc = TensorDesc({2, 4}, ACL_UINT64, ACL_FORMAT_ND); | ||
| 102 | + | ||
| 103 | + auto ut = OP_API_UT(aclnnInplaceZero, INPUT(selfDesc), OUTPUT()); | ||
| 104 | + | ||
| 105 | + uint64_t workspaceSize = 0; | ||
| 106 | + aclnnStatus getWorkspaceResult = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 107 | + EXPECT_EQ(getWorkspaceResult, ACLNN_SUCCESS); | ||
| 108 | +} | ||
| 109 | + | ||
| 92 | // 正常路径, aicore, uint8 | 110 | // 正常路径, aicore, uint8 |
| 93 | TEST_F(l2ZeroTest, l2_zero_test_uint8) | 111 | TEST_F(l2ZeroTest, l2_zero_test_uint8) |
| 94 | { | 112 | { |
| @@ -239,4 +257,4 @@ TEST_F(l2ZeroTest, l2_zero_test_multi_dim_double) | |||
| 239 | uint64_t workspaceSize = 0; | 257 | uint64_t workspaceSize = 0; |
| 240 | aclnnStatus getWorkspaceResult = ut.TestGetWorkspaceSize(&workspaceSize); | 258 | aclnnStatus getWorkspaceResult = ut.TestGetWorkspaceSize(&workspaceSize); |
| 241 | EXPECT_EQ(getWorkspaceResult, ACLNN_SUCCESS); | 259 | EXPECT_EQ(getWorkspaceResult, ACLNN_SUCCESS); |
| 242 | -} | 260 | +} |
self和selfRef指向同一个内存地址,self用int32解析,selfRef用uint32解析,所以这里用self?