已合并
besseli1e算子开发 #3780
besseli1e算子开发 #3780
已合并
kangjiaming创建于 7月3日
共 19 个文件变更+1175-2
@@ -356,6 +356,16 @@
356 <td>AI Core</td>356 <td>AI Core</td>
357 <td>计算指数缩放的第一类零阶修正贝塞尔函数,公式y = exp(-|x|) * I0(x),仅支持图模式调用。</td>357 <td>计算指数缩放的第一类零阶修正贝塞尔函数,公式y = exp(-|x|) * I0(x),仅支持图模式调用。</td>
358 </tr>358 </tr>
359+ <tr>
360+ <td>math</td>
361+ <td><a href="../../math/bessel_i1e/README.md">bessel_i1e</a></td>
362+ <td>√</td>
363+ <td>√</td>
364+ <td>×</td>
365+ <td>√</td>
366+ <td>AI Core</td>
367+ <td>计算指数缩放修正贝塞尔函数(第一类,阶数1)。</td>
368+ </tr>
359 <tr>369 <tr>
360 <td>math</td>370 <td>math</td>
361 <td><a href="../../math/bias_add/README.md">bias_add</a></td>371 <td><a href="../../math/bias_add/README.md">bias_add</a></td>
@@ -0,0 +1,14 @@
1+#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
2+#Copyright(c) 2026 Huawei Technologies Co., Ltd.
3+#This program is free software, you can redistribute it and / or modify it under the terms and conditions of
4+#CANN Open Software License Agreement Version 2.0(the "License").
5+#Please refer to the License for details.You may not use this file except in compliance with the License.
6+#THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+#INCLUDING BUT NOT LIMITED TO NON - INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+#See LICENSE in the root of the software repository for the full text of the License.
9+#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10+#Generated By CANNBot
11+ 
12+set(SUPPORT_COMPUTE_UNIT "ascend910b" "ascend910_93" "ascend950")
13+set(SUPPORT_TILING_DIR "arch32" "arch32" "arch35")
14+add_all_modules_sources(OPTYPE bessel_i1e ACLNNTYPE aclnn_exclude COMPUTE_UNIT ${SUPPORT_COMPUTE_UNIT} TILING_DIR ${SUPPORT_TILING_DIR} DISABLE_IN_OPP TRUE)
@@ -0,0 +1,72 @@
1+<!--
2+Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+-->
4+ 
5+<!-- Generated By CANNBot -->
6+ 
7+# BesselI1e
8+ 
9+## 产品支持情况
10+ 
11+| 产品 | 是否支持 |
12+|:------------------------------------------------| :------: |
13+| <term>Ascend 950PR/Ascend 950DT</term> | √ |
14+| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |
15+| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ |
16+| <term>Atlas 200I/500 A2 推理产品</term> | × |
17+| <term>Atlas 推理系列产品</term> | × |
18+| <term>Atlas 训练系列产品</term> | × |
19+ 
20+## 功能说明
21+ 
22+- 算子功能:计算指数缩放的第一阶修正贝塞尔函数。
23+ 
24+- 计算公式:
25+ 
26+$$out_i = e^{-|input_i|} \cdot I_1(input_i)$$
27+ 
28+其中 $I_1(x)$ 是第一阶修正贝塞尔函数。指数缩放因子 $e^{-|x|}$ 使得函数在大参数值时数值稳定。
29+ 
30+## 参数说明
31+ 
32+<table style="undefined;table-layout: fixed; width: 980px"><colgroup>
33+ <col style="width: 100px">
34+ <col style="width: 150px">
35+ <col style="width: 280px">
36+ <col style="width: 330px">
37+ <col style="width: 120px">
38+ </colgroup>
39+ <thead>
40+ <tr>
41+ <th>参数名</th>
42+ <th>输入/输出/属性</th>
43+ <th>描述</th>
44+ <th>数据类型</th>
45+ <th>数据格式</th>
46+ </tr></thead>
47+ <tbody>
48+ <tr>
49+ <td>x</td>
50+ <td>输入</td>
51+ <td>待进行BesselI1e计算的入参。</td>
52+ <td>FLOAT、FLOAT16、BF16</td>
53+ <td>ND</td>
54+ </tr>
55+ <tr>
56+ <td>y</td>
57+ <td>输出</td>
58+ <td>BesselI1e计算的出参。</td>
59+ <td>FLOAT、FLOAT16、BF16</td>
60+ <td>ND</td>
61+ </tr>
62+ </tbody></table>
63+ 
64+## 约束说明
65+ 
66+无
67+ 
68+## 调用说明
69+ 
70+| 调用方式 | 调用样例 | 说明 |
71+|:---------|:---------|:-----|
72+| 图模式调用 | [test_geir_bessel_i1e](./examples/test_geir_bessel_i1e.cpp) | 通过[算子IR](./op_graph/bessel_i1e_proto.h)构图方式调用BesselI1e算子。 |
@@ -0,0 +1,197 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
A
AAlmost_Miao7月3日

缺少CANNBot标签,排查修改。

likedislike
kangjiaming
7月10日 评论:
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include <iostream>
14+#include <fstream>
15+#include <cstring>
16+#include <cstdint>
17+#include <vector>
18+#include <string>
19+#include <map>
20+#include <cmath>
21+ 
22+#include "graph.h"
23+#include "types.h"
24+#include "tensor.h"
25+#include "ge_error_codes.h"
26+#include "ge_api_types.h"
27+#include "ge_api.h"
28+#include "array_ops.h"
29+#include "ge_ir_build.h"
30+ 
31+#include "../op_graph/bessel_i1e_proto.h"
32+ 
33+#define FAILED -1
34+#define SUCCESS 0
35+ 
36+using namespace ge;
37+ 
38+static std::string GetTime()
39+{
40+ time_t timep;
41+ time(&timep);
42+ char tmp[64];
43+ strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S,000", localtime(&timep));
44+ return tmp;
45+}
46+ 
47+static uint32_t GetDataTypeSize(DataType dt)
48+{
49+ switch (dt) {
50+ case DT_FLOAT:
51+ return 4;
52+ case DT_FLOAT16:
53+ return 2;
54+ default:
55+ return 4;
56+ }
57+}
58+ 
59+static int32_t GenTestData(const std::vector<int64_t>& shapes, Tensor& tensor, TensorDesc& desc, DataType dtype)
60+{
61+ desc.SetRealDimCnt(shapes.size());
62+ size_t size = 1;
63+ for (auto d : shapes)
64+ size *= d;
65+ 
66+ size_t data_len = size * GetDataTypeSize(dtype);
67+ float* pData = new (std::nothrow) float[size];
68+ if (pData == nullptr)
69+ return FAILED;
70+ for (size_t i = 0; i < size; ++i) {
71+ pData[i] = static_cast<float>(i % 10) * 0.5f;
atomgit-bot
atomgit-botatomgit-bot7月3日

🟡 Medium Priority

examples/test_geir_bessel_i1e.cpp:61 使用 new (std::nothrow) float[size] 分配内存,但未检查返回值。若分配失败(返回 nullptr),第 62-63 行的循环 pData[i] = ... 以及第 65 行的 reinterpret_cast<uint8_t*>(pData) 将对空指针解引用,导致段错误。

虽然对于该示例中 shape {32,4,4,4}(仅 2048 元素 ≈ 8KB)分配失败概率极低,但作为示例代码应展示健壮的写法。

建议:在 new 之后增加空指针检查:if (pData == nullptr) return FAILED;

改动建议
71
- pData[i] = static_cast<float>(i % 10) * 0.5f;
71
+ float* pData = new (std::nothrow) float[size];
72
+ if (pData == nullptr) return FAILED;
应用建议
likedislike
不准确?
72+ }
73+ tensor = Tensor(desc, reinterpret_cast<uint8_t*>(pData), data_len);
74+ delete[] pData;
75+ return SUCCESS;
76+}
77+ 
78+static int32_t WriteDataToFile(const std::string& bin_file, uint64_t data_size, uint8_t* data)
79+{
80+ FILE* fp = fopen(bin_file.c_str(), "wb");
81+ if (fp == nullptr)
82+ return FAILED;
83+ fwrite(data, sizeof(uint8_t), data_size, fp);
84+ fclose(fp);
85+ return SUCCESS;
86+}
87+ 
88+int CreateOpInGraph(DataType inDtype, std::vector<ge::Tensor>& input, std::vector<Operator>& inputs,
89+ std::vector<Operator>& outputs, Graph& graph)
90+{
91+ Status ret = SUCCESS;
92+ auto bessel_op = op::BesselI1e("bessel_i1e_0");
93+ 
94+ std::vector<int64_t> xShape = {32, 4, 4, 4};
95+ auto placeholder0 = op::Data("placeholder0").set_attr_index(0);
96+ TensorDesc placeholder0_desc = TensorDesc(ge::Shape(xShape), FORMAT_ND, inDtype);
97+ placeholder0_desc.SetPlacement(ge::kPlacementHost);
98+ placeholder0_desc.SetFormat(FORMAT_ND);
99+ Tensor tensor_placeholder0;
100+ ret = GenTestData(xShape, tensor_placeholder0, placeholder0_desc, inDtype);
101+ if (ret != SUCCESS) {
102+ printf("%s - ERROR: Generate input data failed\n", GetTime().c_str());
103+ return FAILED;
104+ }
105+ placeholder0.update_input_desc_x(placeholder0_desc);
106+ input.push_back(tensor_placeholder0);
107+ graph.AddOp(placeholder0);
108+ bessel_op.set_input_x(placeholder0);
109+ 
110+ TensorDesc y_desc = TensorDesc(ge::Shape(xShape), FORMAT_ND, inDtype);
111+ bessel_op.update_output_desc_y(y_desc);
112+ 
113+ inputs.push_back(placeholder0);
114+ outputs.push_back(bessel_op);
115+ return SUCCESS;
116+}
117+ 
118+int main(int argc, char* argv[])
119+{
120+ const char* graph_name = "bessel_i1e_geir_test";
121+ Graph graph(graph_name);
122+ std::vector<ge::Tensor> input;
123+ 
124+ printf("%s - INFO: Start to initialize GE\n", GetTime().c_str());
125+ std::map<AscendString, AscendString> global_options = {{"ge.exec.deviceId", "0"}, {"ge.graphRunMode", "1"}};
126+ Status ret = ge::GEInitialize(global_options);
127+ if (ret != SUCCESS) {
128+ printf("%s - ERROR: GE initialize failed\n", GetTime().c_str());
129+ return FAILED;
130+ }
131+ 
132+ std::vector<Operator> inputs{};
133+ std::vector<Operator> outputs{};
134+ DataType inDtype = DT_FLOAT;
135+ 
136+ ret = CreateOpInGraph(inDtype, input, inputs, outputs, graph);
137+ if (ret != SUCCESS) {
138+ printf("%s - ERROR: Create op in graph failed\n", GetTime().c_str());
139+ ge::GEFinalize();
140+ return FAILED;
141+ }
142+ 
143+ if (!inputs.empty() && !outputs.empty()) {
144+ graph.SetInputs(inputs).SetOutputs(outputs);
145+ }
146+ 
147+ std::map<AscendString, AscendString> build_options = {};
148+ printf("%s - INFO: Creating session\n", GetTime().c_str());
149+ ge::Session* session = new Session(build_options);
150+ if (session == nullptr) {
151+ printf("%s - ERROR: Create session failed\n", GetTime().c_str());
152+ ge::GEFinalize();
153+ return FAILED;
154+ }
155+ 
156+ std::map<AscendString, AscendString> graph_options = {};
157+ uint32_t graph_id = 0;
158+ ret = session->AddGraph(graph_id, graph, graph_options);
159+ if (ret != SUCCESS) {
160+ printf("%s - ERROR: Add graph failed\n", GetTime().c_str());
161+ delete session;
162+ ge::GEFinalize();
163+ return FAILED;
164+ }
165+ 
166+ printf("%s - INFO: Running graph\n", GetTime().c_str());
167+ std::vector<ge::Tensor> output;
168+ ret = session->RunGraph(graph_id, input, output);
169+ if (ret != SUCCESS) {
170+ printf("%s - ERROR: Run graph failed\n", GetTime().c_str());
171+ delete session;
172+ ge::GEFinalize();
173+ return FAILED;
174+ }
175+ printf("%s - INFO: Run graph success\n", GetTime().c_str());
176+ 
177+ for (size_t i = 0; i < output.size(); i++) {
178+ std::string output_file = "./bessel_i1e_geir_output_" + std::to_string(i) + ".bin";
179+ uint8_t* output_data = output[i].GetData();
180+ int64_t output_shape_size = output[i].GetTensorDesc().GetShape().GetShapeSize();
181+ uint64_t data_size = static_cast<uint64_t>(output_shape_size) *
182+ GetDataTypeSize(output[i].GetTensorDesc().GetDataType());
183+ WriteDataToFile(output_file, data_size, output_data);
184+ printf("%s - INFO: Output %zu written to %s (size=%lu bytes)\n", GetTime().c_str(), i, output_file.c_str(),
185+ data_size);
186+ }
187+ 
188+ printf("%s - INFO: Finalizing\n", GetTime().c_str());
189+ delete session;
190+ ret = ge::GEFinalize();
191+ if (ret != SUCCESS) {
192+ printf("%s - ERROR: GE finalize failed\n", GetTime().c_str());
193+ return FAILED;
194+ }
195+ printf("%s - INFO: Done\n", GetTime().c_str());
196+ return SUCCESS;
197+}
@@ -0,0 +1,30 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "register/op_impl_registry.h"
14+#include "log/log.h"
15+ 
16+using namespace ge;
17+ 
18+namespace ops {
19+ 
20+static ge::graphStatus InferDataTypeForBesselI1e(gert::InferDataTypeContext* context)
21+{
22+ OP_LOGI(context->GetNodeName(), "Begin InferDataTypeForBesselI1e");
23+ const ge::DataType xDataType = context->GetInputDataType(0);
24+ context->SetOutputDataType(0, xDataType);
25+ return ge::GRAPH_SUCCESS;
26+}
27+ 
28+IMPL_OP(BesselI1e).InferDataType(InferDataTypeForBesselI1e);
29+ 
30+} // namespace ops
@@ -0,0 +1,42 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#ifndef OPS_OP_PROTO_INC_BESSEL_I1E_H_
14+#define OPS_OP_PROTO_INC_BESSEL_I1E_H_
15+ 
16+#include "graph/operator_reg.h"
17+#include "graph/types.h"
18+ 
19+namespace ge {
20+ 
21+/**
22+ * @brief Computes the Bessel i1e function of "x" element-wise.
23+ * Exponentially scaled modified Bessel function of order 1
24+ * defined as: bessel_i1e(x) = exp(-abs(x)) * bessel_i1(x).
25+ *
26+ * @par Inputs:
27+ * @li x: A tensor of type bfloat16, float16, float32, or float64.
28+ *
29+ * @par Outputs:
30+ * @li y: A tensor. Has the same dtype as "x".
31+ *
32+ * @par Third-party framework compatibility
33+ * Compatible with the TensorFlow operator BesselI1e.
34+ */
35+REG_OP(BesselI1e)
36+ .INPUT(x, TensorType({FloatingDataType, DT_BF16}))
37+ .OUTPUT(y, TensorType({FloatingDataType, DT_BF16}))
38+ .OP_END_FACTORY_REG(BesselI1e)
39+ 
40+} // namespace ge
41+ 
42+#endif // OPS_OP_PROTO_INC_BESSEL_I1E_H_
@@ -0,0 +1,13 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "../arch35/bessel_i1e_tiling_arch35.cpp"
@@ -0,0 +1,141 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "register/op_def_registry.h"
14+#include "op_common/log/log.h"
15+#include "op_common/op_host/util/math_util.h"
16+#include "op_common/op_host/util/platform_util.h"
17+#include "../../op_kernel/arch35/bessel_i1e_tiling_data.h"
18+#include "../../op_kernel/arch35/bessel_i1e_tiling_key.h"
19+ 
20+namespace optiling {
21+ 
22+using Ops::Base::CeilAlign;
23+using Ops::Base::CeilDiv;
24+using Ops::Base::FloorAlign;
25+using Ops::Base::FloorDiv;
26+using Ops::Base::GetUbBlockSize;
27+ 
28+constexpr uint32_t WS_SYS_SIZE = 0U;
29+constexpr size_t WORKSPACE_NUM = 1;
30+constexpr int64_t INTERNAL_QUEUE_COUNT = 3;
31+constexpr int64_t DOUBLE_BUFFER_FACTOR = 2;
32+ 
33+static const gert::Shape g_vec_1_shape = {1};
34+ 
35+static inline const gert::Shape EnsureNotScalar(const gert::Shape& in_shape)
36+{
37+ if (in_shape.GetDimNum() == 0) {
38+ return g_vec_1_shape;
39+ }
40+ return in_shape;
41+}
42+ 
43+static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t* ubSize, int64_t* coreNum)
44+{
45+ fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo();
46+ OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr);
47+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr);
48+ *coreNum = ascendcPlatform.GetCoreNumAiv();
49+ OP_CHECK_IF(*coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED);
50+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, *ubSize);
51+ OP_CHECK_IF(*ubSize == 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED);
52+ return ge::GRAPH_SUCCESS;
53+}
54+ 
55+static ge::graphStatus GetShapeAttrsInfo(gert::TilingContext* context, int64_t* totalIdx, ge::DataType* dataType)
56+{
57+ auto inputX = context->GetInputShape(0);
58+ OP_CHECK_NULL_WITH_CONTEXT(context, inputX);
59+ auto inputShapeX = EnsureNotScalar(inputX->GetStorageShape());
60+ auto outY = context->GetOutputShape(0);
61+ OP_CHECK_NULL_WITH_CONTEXT(context, outY);
62+ auto outShapeY = EnsureNotScalar(outY->GetStorageShape());
63+ 
64+ OP_CHECK_IF(inputShapeX.GetShapeSize() != outShapeY.GetShapeSize(),
65+ OP_LOGE(context, "BesselI1e: input and output shape size mismatch: x=%ld, y=%ld",
66+ inputShapeX.GetShapeSize(), outShapeY.GetShapeSize()),
67+ return ge::GRAPH_FAILED);
68+ 
69+ *totalIdx = inputShapeX.GetShapeSize();
70+ const std::set<ge::DataType> supportedDtype = {ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16};
71+ auto inputDesc = context->GetInputDesc(0);
72+ OP_CHECK_NULL_WITH_CONTEXT(context, inputDesc);
73+ *dataType = inputDesc->GetDataType();
74+ OP_CHECK_IF(supportedDtype.count(*dataType) == 0, OP_LOGE(context, "invalid dtype"), return ge::GRAPH_FAILED);
75+ return ge::GRAPH_SUCCESS;
76+}
77+ 
78+static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context)
79+{
80+ size_t* currentWorkspace = context->GetWorkspaceSizes(WORKSPACE_NUM);
81+ OP_CHECK_NULL_WITH_CONTEXT(context, currentWorkspace);
82+ currentWorkspace[0] = WS_SYS_SIZE;
83+ return ge::GRAPH_SUCCESS;
84+}
85+ 
86+static ge::graphStatus BesselI1eTilingFunc(gert::TilingContext* context)
87+{
88+ OP_LOGI(context->GetNodeName(), "Enter BesselI1eTilingFunc");
89+ uint64_t ubSize;
90+ int64_t coreNum;
91+ OP_CHECK_IF(GetPlatformInfo(context, &ubSize, &coreNum) != ge::GRAPH_SUCCESS,
92+ OP_LOGE(context, "GetPlatformInfo error"), return ge::GRAPH_FAILED);
93+ 
94+ int64_t totalIdx;
95+ ge::DataType dataType;
96+ OP_CHECK_IF(GetShapeAttrsInfo(context, &totalIdx, &dataType) != ge::GRAPH_SUCCESS,
97+ OP_LOGE(context, "GetShapeAttrsInfo error"), return ge::GRAPH_FAILED);
98+ 
99+ OP_CHECK_IF(GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetWorkspaceSize error"),
100+ return ge::GRAPH_FAILED);
101+ 
102+ BesselI1eTilingData* tiling = context->GetTilingData<BesselI1eTilingData>();
103+ OP_CHECK_NULL_WITH_CONTEXT(context, tiling);
104+ OP_CHECK_IF(memset_s(tiling, sizeof(BesselI1eTilingData), 0, sizeof(BesselI1eTilingData)) != EOK,
105+ OP_LOGE(context, "set tiling data error"), return ge::GRAPH_FAILED);
106+ 
107+ if (totalIdx == 0) {
108+ context->SetBlockDim(1);
109+ ASCENDC_TPL_SEL_PARAM(context, static_cast<uint32_t>(dataType));
110+ return ge::GRAPH_SUCCESS;
111+ }
112+ 
113+ int64_t ubBlockSize = Ops::Base::GetUbBlockSize(context);
114+ int64_t dtypeSize = (dataType == ge::DT_FLOAT) ? static_cast<int64_t>(sizeof(float)) :
115+ static_cast<int64_t>(sizeof(uint16_t));
116+ tiling->totalNum = totalIdx;
117+ tiling->blockFactor = CeilAlign(CeilDiv(totalIdx, coreNum), ubBlockSize / dtypeSize);
118+ int64_t usedCoreNum = Ops::Base::CeilDiv(totalIdx, tiling->blockFactor);
119+ 
120+ int64_t bufferNum = INTERNAL_QUEUE_COUNT * DOUBLE_BUFFER_FACTOR;
121+ tiling->ubFactor = Ops::Base::FloorAlign(
122+ Ops::Base::FloorDiv((static_cast<int64_t>(ubSize) / static_cast<int64_t>(sizeof(float))), bufferNum),
123+ ubBlockSize / static_cast<int64_t>(sizeof(float)));
124+ 
125+ context->SetBlockDim(usedCoreNum);
126+ 
127+ uint32_t dTypeX = static_cast<uint32_t>(dataType);
128+ ASCENDC_TPL_SEL_PARAM(context, dTypeX);
129+ return ge::GRAPH_SUCCESS;
130+}
131+ 
132+static ge::graphStatus TilingParseForBesselI1e([[maybe_unused]] gert::TilingParseContext* context)
133+{
134+ return ge::GRAPH_SUCCESS;
135+}
136+ 
137+struct BesselI1eCompileInfo {};
138+ 
139+IMPL_OP_OPTILING(BesselI1e).Tiling(BesselI1eTilingFunc).TilingParse<BesselI1eCompileInfo>(TilingParseForBesselI1e);
140+ 
141+} // namespace optiling
@@ -0,0 +1,47 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "register/op_def_registry.h"
14+ 
15+namespace ops {
16+class BesselI1e : public OpDef {
17+public:
18+ explicit BesselI1e(const char* name) : OpDef(name)
19+ {
20+ this->Input("x")
21+ .ParamType(REQUIRED)
22+ .DataType({ge::DT_BF16, ge::DT_FLOAT16, ge::DT_FLOAT})
23+ .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
24+ .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
25+ .AutoContiguous();
26+ this->Output("y")
27+ .ParamType(REQUIRED)
28+ .DataType({ge::DT_BF16, ge::DT_FLOAT16, ge::DT_FLOAT})
29+ .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
30+ .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
31+ .AutoContiguous();
32+ 
33+ OpAICoreConfig aiCoreConfig;
34+ aiCoreConfig.DynamicCompileStaticFlag(true)
35+ .DynamicFormatFlag(false)
36+ .DynamicRankSupportFlag(true)
37+ .DynamicShapeSupportFlag(true)
38+ .NeedCheckSupportFlag(false)
39+ .PrecisionReduceFlag(true)
40+ .ExtendCfgInfo("opFile.value", "bessel_i1e_apt");
41+ this->AICore().AddConfig("ascend910b", aiCoreConfig);
42+ this->AICore().AddConfig("ascend910_93", aiCoreConfig);
43+ this->AICore().AddConfig("ascend950", aiCoreConfig);
44+ }
45+};
46+OP_ADD(BesselI1e);
47+} // namespace ops
@@ -0,0 +1,36 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "register/op_impl_registry.h"
14+#include "exe_graph/runtime/infer_shape_context.h"
15+#include "op_common/log/log.h"
16+ 
17+using namespace ge;
18+ 
19+namespace ops {
20+ 
21+static ge::graphStatus InferShape4BesselI1e(gert::InferShapeContext* context)
22+{
23+ const gert::Shape* input_shape = context->GetInputShape(0);
24+ OP_CHECK_NULL_WITH_CONTEXT(context, input_shape);
25+ 
26+ gert::Shape* output_shape = context->GetOutputShape(0);
27+ OP_CHECK_NULL_WITH_CONTEXT(context, output_shape);
28+ 
29+ *output_shape = *input_shape;
30+ 
31+ return ge::GRAPH_SUCCESS;
32+}
33+ 
34+IMPL_OP_INFERSHAPE(BesselI1e).InferShape(InferShape4BesselI1e);
35+ 
36+} // namespace ops
@@ -0,0 +1,229 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#ifndef BESSEL_I1E_H
14+#define BESSEL_I1E_H
15+ 
16+#include "kernel_operator.h"
17+#include "kernel_tiling/kernel_tiling.h"
18+#include "bessel_i1e_tiling_data.h"
19+#include "bessel_i1e_tiling_key.h"
20+ 
21+namespace NsBesselI1e {
22+ 
23+using namespace AscendC;
24+ 
25+constexpr float SEGMENT_POINT = 3.75f;
26+constexpr float INV_SEGMENT = 0.26666666666666666f;
27+constexpr float QUARTER = 0.25f;
28+ 
29+constexpr float EXP_COEFF_0 = 1.0f;
30+constexpr float EXP_COEFF_1 = 1.0f;
31+constexpr float EXP_COEFF_2 = 0.5f;
32+constexpr float EXP_COEFF_3 = 0.16666667f;
33+constexpr float EXP_COEFF_4 = 0.04166667f;
34+constexpr float EXP_COEFF_5 = 0.00833333f;
35+constexpr float EXP_COEFF_6 = 0.00138889f;
36+constexpr float EXP_COEFF_7 = 0.00019841f;
37+constexpr float EXP_COEFF_8 = 0.00002480f;
38+ 
39+constexpr float itrBefore[7] = {0.5f, 0.87890594f, 0.51498869f, 0.15084934f, 0.02658773f, 0.00301532f, 0.00032411f};
40+ 
41+constexpr float itrAfter[9] = {0.39894228f, -0.03988024f, -0.00362018f, 0.00163801f, -0.01031555f,
42+ 0.02282967f, -0.02895312f, 0.01787654f, -0.00420059f};
43+ 
44+template <typename T>
45+class BesselI1e {
46+ static constexpr int32_t BUFFER_NUM = 2;
47+ 
48+public:
49+ __aicore__ inline BesselI1e(){};
50+ 
51+ __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, const BesselI1eTilingData* tilingData);
52+ __aicore__ inline void Process();
53+ 
54+private:
55+ __aicore__ inline void CopyIn(int64_t progress, int64_t currentNum);
56+ __aicore__ inline void CopyOut(int64_t progress, int64_t currentNum);
57+ __aicore__ inline void Compute(int64_t currentNum);
58+ 
59+private:
60+ TPipe pipe;
61+ TQue<QuePosition::VECIN, BUFFER_NUM> inputQueueX;
62+ TQue<QuePosition::VECOUT, BUFFER_NUM> outputQueueY;
63+ TQue<QuePosition::VECOUT, BUFFER_NUM> tmpQueue1;
64+ 
65+ GlobalTensor<T> inputGMX;
66+ GlobalTensor<T> outputGMY;
67+ 
68+ int64_t blockLength_ = 0;
69+ int64_t ubLength_ = 0;
70+};
71+ 
72+template <typename T>
73+__aicore__ inline void BesselI1e<T>::Init(GM_ADDR x, GM_ADDR y, const BesselI1eTilingData* tilingData)
74+{
75+ int64_t remainderLength = tilingData->totalNum - tilingData->blockFactor * AscendC::GetBlockIdx();
76+ blockLength_ = (remainderLength > tilingData->blockFactor) ? tilingData->blockFactor : remainderLength;
77+ ubLength_ = tilingData->ubFactor;
78+ 
79+ inputGMX.SetGlobalBuffer((__gm__ T*)x + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_);
80+ outputGMY.SetGlobalBuffer((__gm__ T*)y + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_);
81+ 
82+ pipe.InitBuffer(inputQueueX, BUFFER_NUM, ubLength_ * sizeof(float));
83+ pipe.InitBuffer(outputQueueY, BUFFER_NUM, ubLength_ * sizeof(float));
84+ pipe.InitBuffer(tmpQueue1, BUFFER_NUM, ubLength_ * sizeof(float));
85+}
86+ 
87+template <typename T>
88+__aicore__ inline void BesselI1e<T>::CopyIn(int64_t progress, int64_t currentNum)
89+{
90+ AscendC::LocalTensor<float> xLocal = inputQueueX.template AllocTensor<float>();
91+ if constexpr (std::is_same_v<T, half>) {
92+ AscendC::LocalTensor<half> tmpHalf = tmpQueue1.template AllocTensor<half>();
93+ AscendC::DataCopyExtParams copyParams;
94+ copyParams.blockCount = 1;
95+ copyParams.blockLen = currentNum * sizeof(half);
S
Ssunday7月10日

CopyIn/CopyOut 的尾块 DMA 可能小于 32 字节。当 blockLength_ 不能被 ubFactor 整除时,最后一次迭代 currentNum 可能为 1~31 元素,此时 blockLen = currentNum * sizeof(T) 可能 < 32 字节(fp16 最严重:1 元素 = 2 字节),违反 AscendC DMA 32 字节对齐要求。建议对尾块使用 isPad=true 的 DataCopyPad 配合 DataCopyPadParams 补齐至 32 字节。CopyOut 中同样存在此问题(第 139、150、160 行)。

likedislike
96+ copyParams.srcStride = 0;
97+ copyParams.dstStride = 0;
98+ copyParams.rsv = 0;
99+ AscendC::DataCopyPad(tmpHalf, inputGMX[progress * ubLength_], copyParams, {false, 0, 0, 0});
100+ for (int64_t i = 0; i < currentNum; i++) {
101+ xLocal.SetValue(i, static_cast<float>(tmpHalf.GetValue(i)));
102+ }
103+ tmpQueue1.FreeTensor(tmpHalf);
104+ } else if constexpr (std::is_same_v<T, bfloat16_t>) {
105+ AscendC::LocalTensor<bfloat16_t> tmpBf16 = tmpQueue1.template AllocTensor<bfloat16_t>();
106+ AscendC::DataCopyExtParams copyParams;
107+ copyParams.blockCount = 1;
108+ copyParams.blockLen = currentNum * sizeof(bfloat16_t);
109+ copyParams.srcStride = 0;
110+ copyParams.dstStride = 0;
111+ copyParams.rsv = 0;
112+ AscendC::DataCopyPad(tmpBf16, inputGMX[progress * ubLength_], copyParams, {false, 0, 0, 0});
113+ AscendC::Cast(xLocal, tmpBf16, AscendC::RoundMode::CAST_NONE, currentNum);
114+ tmpQueue1.FreeTensor(tmpBf16);
115+ } else {
116+ AscendC::DataCopyExtParams copyParams;
117+ copyParams.blockCount = 1;
118+ copyParams.blockLen = currentNum * sizeof(float);
119+ copyParams.srcStride = 0;
120+ copyParams.dstStride = 0;
121+ copyParams.rsv = 0;
122+ AscendC::DataCopyPad(xLocal, inputGMX[progress * ubLength_], copyParams, {false, 0, 0, 0});
123+ }
124+ inputQueueX.EnQue(xLocal);
125+}
126+ 
127+template <typename T>
128+__aicore__ inline void BesselI1e<T>::CopyOut(int64_t progress, int64_t currentNum)
129+{
130+ AscendC::LocalTensor<float> yLocal = outputQueueY.template DeQue<float>();
131+ if constexpr (std::is_same_v<T, half>) {
132+ AscendC::LocalTensor<half> tmpHalf = tmpQueue1.template AllocTensor<half>();
133+ for (int64_t i = 0; i < currentNum; i++) {
134+ tmpHalf.SetValue(i, static_cast<half>(yLocal.GetValue(i)));
135+ }
136+ AscendC::DataCopyExtParams copyParams;
137+ copyParams.blockCount = 1;
138+ copyParams.blockLen = currentNum * sizeof(half);
139+ copyParams.srcStride = 0;
140+ copyParams.dstStride = 0;
141+ copyParams.rsv = 0;
142+ AscendC::DataCopyPad(outputGMY[progress * ubLength_], tmpHalf, copyParams);
143+ tmpQueue1.FreeTensor(tmpHalf);
144+ } else if constexpr (std::is_same_v<T, bfloat16_t>) {
145+ AscendC::LocalTensor<bfloat16_t> tmpBf16 = tmpQueue1.template AllocTensor<bfloat16_t>();
146+ AscendC::Cast(tmpBf16, yLocal, AscendC::RoundMode::CAST_RINT, currentNum);
147+ AscendC::DataCopyExtParams copyParams;
148+ copyParams.blockCount = 1;
149+ copyParams.blockLen = currentNum * sizeof(bfloat16_t);
150+ copyParams.srcStride = 0;
151+ copyParams.dstStride = 0;
152+ copyParams.rsv = 0;
153+ AscendC::DataCopyPad(outputGMY[progress * ubLength_], tmpBf16, copyParams);
154+ tmpQueue1.FreeTensor(tmpBf16);
155+ } else {
156+ AscendC::DataCopyExtParams copyParams;
157+ copyParams.blockCount = 1;
158+ copyParams.blockLen = currentNum * sizeof(float);
159+ copyParams.srcStride = 0;
160+ copyParams.dstStride = 0;
161+ copyParams.rsv = 0;
162+ AscendC::DataCopyPad(outputGMY[progress * ubLength_], yLocal, copyParams);
163+ }
164+ outputQueueY.FreeTensor(yLocal);
165+}
166+ 
167+template <typename T>
168+__aicore__ inline void BesselI1e<T>::Compute(int64_t currentNum)
169+{
170+ AscendC::LocalTensor<float> xLocal = inputQueueX.template DeQue<float>();
171+ AscendC::LocalTensor<float> yLocal = outputQueueY.template AllocTensor<float>();
172+ 
173+ for (int64_t i = 0; i < currentNum; i++) {
174+ float x = xLocal.GetValue(i);
175+ float absX = (x >= 0.0f) ? x : -x;
176+ float sign = (x >= 0.0f) ? 1.0f : -1.0f;
177+ float result;
178+ 
179+ if (absX < SEGMENT_POINT) {
180+ float t = absX * INV_SEGMENT;
181+ float t2 = t * t;
182+ float poly = itrBefore[6];
183+ for (int k = 5; k >= 0; k--) {
184+ poly = poly * t2 + itrBefore[k];
185+ }
186+ float q = absX * QUARTER;
187+ float e = EXP_COEFF_0 -
188+ q * (EXP_COEFF_1 -
189+ q * (EXP_COEFF_2 -
190+ q * (EXP_COEFF_3 -
191+ q * (EXP_COEFF_4 -
192+ q * (EXP_COEFF_5 -
193+ q * (EXP_COEFF_6 - q * (EXP_COEFF_7 - q * EXP_COEFF_8)))))));
194+ e = e * e;
195+ e = e * e;
196+ result = e * absX * poly;
197+ } else {
198+ float t = SEGMENT_POINT / absX;
199+ float poly = itrAfter[8];
200+ for (int k = 7; k >= 0; k--) {
201+ poly = poly * t + itrAfter[k];
202+ }
203+ float sqrtX = sqrt(absX);
204+ result = poly / sqrtX;
205+ }
206+ yLocal.SetValue(i, sign * result);
207+ }
208+ 
209+ outputQueueY.template EnQue<float>(yLocal);
210+ inputQueueX.FreeTensor(xLocal);
211+}
212+ 
213+template <typename T>
214+__aicore__ inline void BesselI1e<T>::Process()
215+{
216+ if (blockLength_ <= 0) {
217+ return;
218+ }
219+ int64_t loopCount = (blockLength_ + ubLength_ - 1) / ubLength_;
atomgit-bot
atomgit-botatomgit-bot7月3日

🟠 High Priority

在 tiling 代码 BesselI1eTilingFunc(bessel_i1e_tiling_arch35.cpp:108-112)中,当 totalIdx == 0(空 tensor,如 shape [0,3])时,提前返回前仅做了 memset_s 清零,导致 tiling->ubFactor 保持为 0。kernel 端 Init 将 ubLength_ 赋值为 0,blockLength_ 也为 0。随后 Process()(bessel_i1e.h:179)执行: int64_t loopCount = (blockLength_ + ubLength_ - 1) / ubLength_; 即 (-1) / 0,触发整数除零 → AICore 异常/设备 crash。

触发条件:输入为空 tensor(元素个数为 0),如 CSV 测试用例 L0_017/L0_018(shape [0,3])。

修复方向:在 tiling 的 totalIdx==0 分支中将 tiling->ubFactor 设为 ≥1 的最小合法值(如 1 或对齐后的最小 UB 块大小),或在 kernel Process() 入口增加 if (blockLength_ == 0) return; 的守卫。

likedislike
不准确?
220+ for (int64_t i = 0; i < loopCount; i++) {
221+ int64_t currentNum = (i == (loopCount - 1)) ? (blockLength_ - ubLength_ * i) : ubLength_;
222+ CopyIn(i, currentNum);
223+ Compute(currentNum);
224+ CopyOut(i, currentNum);
225+ }
226+}
227+ 
228+} // namespace NsBesselI1e
229+#endif // BESSEL_I1E_H
@@ -0,0 +1,21 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#ifndef _BESSEL_I1E_TILING_DATA_H_
14+#define _BESSEL_I1E_TILING_DATA_H_
15+ 
16+struct BesselI1eTilingData {
17+ int64_t totalNum = 0;
18+ int64_t blockFactor = 0;
19+ int64_t ubFactor = 0;
20+};
21+#endif
@@ -0,0 +1,25 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#ifndef __BESSEL_I1E_TILING_KEY_H__
14+#define __BESSEL_I1E_TILING_KEY_H__
15+ 
16+#include "ascendc/host_api/tiling/template_argument.h"
17+ 
18+ASCENDC_TPL_ARGS_DECL(BesselI1e,
19+ ASCENDC_TPL_DATATYPE_DECL(D_T_X, C_DT_FLOAT, C_DT_FLOAT16, C_DT_BF16, ASCENDC_TPL_INPUT(0)));
20+ 
21+ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL(ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_FLOAT)),
22+ ASCENDC_TPL_ARGS_SEL(ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_FLOAT16)),
23+ ASCENDC_TPL_ARGS_SEL(ASCENDC_TPL_DATATYPE_SEL(D_T_X, C_DT_BF16)), );
24+ 
25+#endif
@@ -0,0 +1,24 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include "arch35/bessel_i1e.h"
14+ 
15+template <typename D_T_X>
16+__global__ __aicore__ void bessel_i1e(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling)
17+{
18+ KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY);
19+ REGISTER_TILING_DEFAULT(BesselI1eTilingData);
20+ GET_TILING_DATA_WITH_STRUCT(BesselI1eTilingData, tilingData, tiling);
21+ NsBesselI1e::BesselI1e<D_T_X> op;
22+ op.Init(x, y, &tilingData);
23+ op.Process();
24+}
@@ -0,0 +1,8 @@
1+cmake_minimum_required(VERSION 3.16.0)
2+project(bessel_i1e_ut CXX)
3+ 
4+set(CMAKE_CXX_STANDARD 17)
5+set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+ 
7+add_executable(test_bessel_i1e_ut test_bessel_i1e_ut.cpp)
8+target_compile_options(test_bessel_i1e_ut PRIVATE -Wall -Wextra -O2)
@@ -0,0 +1,45 @@
1+#!/bin/bash
2+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+# CANN Open Software License Agreement Version 2.0 (the "License").
5+# Please refer to the License for details. You may not use this file except in compliance with the License.
6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+# See LICENSE in the root of the software repository for the full text of the License.
9+# ============================================================================
10+set -e
11+ 
12+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13+BUILD_DIR="${SCRIPT_DIR}/build"
14+ 
15+echo "========================================"
16+echo "BesselI1e UT Tests"
17+echo "========================================"
18+ 
19+rm -rf "${BUILD_DIR}"
20+mkdir -p "${BUILD_DIR}"
21+cd "${BUILD_DIR}"
22+ 
23+echo "Configuring..."
24+cmake .. > /dev/null
25+ 
26+echo "Building..."
27+make -j$(nproc) > /dev/null
28+ 
29+echo "Running..."
30+echo ""
31+./test_bessel_i1e_ut
32+RESULT=$?
33+ 
34+echo ""
35+if [ $RESULT -eq 0 ]; then
36+ echo "========================================"
37+ echo "UT Result: PASS"
38+ echo "========================================"
39+else
40+ echo "========================================"
41+ echo "UT Result: FAIL"
42+ echo "========================================"
43+fi
44+ 
45+exit $RESULT
@@ -0,0 +1,207 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ *
10+ * Generated By CANNBot
11+ */
12+ 
13+#include <iostream>
14+#include <cmath>
15+#include <vector>
16+#include <cassert>
17+#include <cstdint>
18+ 
19+static const float kItrBefore[7] = {0.5f, 0.87890594f, 0.51498869f, 0.15084934f, 0.02658773f, 0.00301532f, 0.00032411f};
20+ 
21+static const float kItrAfter[9] = {0.39894228f, -0.03988024f, -0.00362018f, 0.00163801f, -0.01031555f,
22+ 0.02282967f, -0.02895312f, 0.01787654f, -0.00420059f};
23+ 
24+static const float kConstLimit = 3.75f;
25+static const float kInvSegment = 0.26666666666666666f;
26+ 
27+float ComputeI1eScalar(float x)
28+{
29+ float absX = fabsf(x);
30+ float sign = (x >= 0.0f) ? 1.0f : -1.0f;
31+ float result;
32+ 
33+ if (absX < kConstLimit) {
34+ float t = absX * kInvSegment;
35+ float t2 = t * t;
36+ float poly = kItrBefore[6];
37+ for (int k = 5; k >= 0; k--) {
38+ poly = poly * t2 + kItrBefore[k];
39+ }
40+ float q = absX * 0.25f;
41+ float e = 1.0f -
42+ q * (1.0f - q * (0.5f - q * (0.16666667f -
43+ q * (0.04166667f -
44+ q * (0.00833333f -
45+ q * (0.00138889f - q * (0.00019841f - q * 0.00002480f)))))));
46+ e = e * e;
47+ e = e * e;
48+ result = e * absX * poly;
49+ } else {
50+ float t = kConstLimit / absX;
51+ float poly = kItrAfter[8];
52+ for (int k = 7; k >= 0; k--) {
53+ poly = poly * t + kItrAfter[k];
54+ }
55+ float sqrtX = sqrtf(absX);
56+ result = poly / sqrtX;
57+ }
58+ return sign * result;
59+}
60+ 
61+struct TilingData {
62+ int64_t totalNum;
63+ int64_t blockFactor;
64+ int64_t ubFactor;
65+};
66+ 
67+void ComputeTiling(int64_t dim0, int32_t typeSize, int64_t ubSize, int64_t coreNum, TilingData& tiling)
68+{
69+ constexpr int64_t MIN_TILING_BITS = 32768;
70+ constexpr int64_t ELEM_ALIGN = 512;
71+ constexpr int64_t SINGLE_BUF_COUNT = 5;
72+ constexpr int64_t DOUBLE_BUF_COUNT = 10;
73+ 
74+ tiling.totalNum = dim0;
75+ 
76+ if (dim0 == 0) {
77+ tiling.blockFactor = 0;
78+ tiling.ubFactor = 0;
79+ return;
80+ }
81+ 
82+ int64_t minDtypeBits = typeSize * 8;
83+ int64_t computedCoreNum = (dim0 * minDtypeBits + MIN_TILING_BITS - 1) / MIN_TILING_BITS;
84+ if (computedCoreNum > coreNum)
85+ computedCoreNum = coreNum;
86+ 
87+ tiling.blockFactor = ((dim0 + computedCoreNum - 1) / computedCoreNum + ELEM_ALIGN - 1) / ELEM_ALIGN * ELEM_ALIGN;
atomgit-bot
atomgit-botatomgit-bot7月3日

🟡 Medium Priority

文件 test_bessel_i1e_ut.cpp 第 73 行:computedCoreNum = (dim0 * minDtypeBits + MIN_TILING_BITS - 1) / MIN_TILING_BITS。当 dim0=0 时,computedCoreNum = (32767)/32768 = 0(整数除法)。随后第 76 行 ((dim0 + computedCoreNum - 1) / computedCoreNum + ...) 在 computedCoreNum=0 时触发整数除零,属于未定义行为,在 Linux 下通常导致 SIGFPE 信号使进程异常终止。 该问题由第 156 行的测试用例 ComputeTiling(0, 4, 248 * 1024, 28, t) 直接触发,导致空 Tensor 的 tiling 测试崩溃而非正常验证。

建议:在 dim0=0 时提前返回,或者当 computedCoreNum=0 时将其设为 1 作为保底值。建议在 ComputeTiling 函数开头增加:if (dim0 == 0) { tiling.totalNum = 0; tiling.blockFactor = 0; tiling.ubFactor = 0; return; }

likedislike
不准确?
88+ 
89+ int64_t useDoubleBuffer = (typeSize == 2) ? 1 : ((dim0 > 1024) ? 1 : 0);
90+ int64_t bufferNum = useDoubleBuffer ? DOUBLE_BUF_COUNT : SINGLE_BUF_COUNT;
91+ int64_t bufferDivisor = bufferNum * typeSize;
92+ int64_t maxElemNum = (ubSize * 8) / bufferDivisor;
93+ int64_t alignFactor = 256 * 8 / minDtypeBits;
94+ tiling.ubFactor = (maxElemNum / alignFactor) * alignFactor;
95+}
96+ 
97+int passed = 0;
98+int failed = 0;
99+ 
100+void Check(bool cond, const char* name)
101+{
102+ if (cond) {
103+ std::cout << " [PASS] " << name << std::endl;
104+ passed++;
105+ } else {
106+ std::cout << " [FAIL] " << name << std::endl;
107+ failed++;
108+ }
109+}
110+ 
111+void TestGoldenFunction()
112+{
113+ std::cout << "\n=== Golden Function Tests ===" << std::endl;
114+ 
115+ Check(fabsf(ComputeI1eScalar(0.0f)) < 1e-6f, "i1e(0) = 0");
116+ Check(fabsf(ComputeI1eScalar(1.0f) - 0.2079104f) < 1e-4f, "i1e(1.0) ≈ 0.2079");
117+ Check(fabsf(ComputeI1eScalar(-1.0f) + 0.2079104f) < 1e-4f, "i1e(-1.0) ≈ -0.2079 (odd)");
118+ Check(fabsf(ComputeI1eScalar(2.0f) - 0.2152693f) < 1e-4f, "i1e(2.0) ≈ 0.2153");
119+ Check(fabsf(ComputeI1eScalar(5.0f) - 0.1639723f) < 1e-4f, "i1e(5.0) ≈ 0.1640");
120+ Check(fabsf(ComputeI1eScalar(10.0f) - 0.1212627f) < 1e-3f, "i1e(10.0) ≈ 0.1213");
121+ Check(fabsf(ComputeI1eScalar(100.0f) - 0.0397442f) < 1e-3f, "i1e(100.0) ≈ 0.0397");
122+ Check(fabsf(ComputeI1eScalar(-5.0f) + 0.1639723f) < 1e-4f, "i1e(-5.0) ≈ -0.1640 (odd)");
123+ 
124+ float seg1 = ComputeI1eScalar(3.74f);
125+ float seg2 = ComputeI1eScalar(3.76f);
126+ Check(fabsf(seg1 - seg2) < 0.01f, "segment continuity at |x|=3.75");
127+ 
128+ Check(ComputeI1eScalar(1000.0f) > 0.0f, "i1e(1000) > 0 (no overflow)");
129+ Check(ComputeI1eScalar(1000.0f) < 0.1f, "i1e(1000) < 0.1 (asymptotic decay)");
130+}
131+ 
132+void TestTilingComputation()
133+{
134+ std::cout << "\n=== Tiling Computation Tests ===" << std::endl;
135+ 
136+ {
137+ TilingData t;
138+ ComputeTiling(1024, 4, 248 * 1024, 28, t);
139+ Check(t.totalNum == 1024, "FP32 small: totalNum=1024");
140+ Check(t.blockFactor >= 1024, "FP32 small: blockFactor >= totalNum");
141+ Check(t.ubFactor > 0, "FP32 small: ubFactor > 0");
142+ Check(t.ubFactor % 64 == 0, "FP32 small: ubFactor aligned to 64 (256B/4B)");
143+ }
144+ 
145+ {
146+ TilingData t;
147+ ComputeTiling(100000, 4, 248 * 1024, 28, t);
148+ Check(t.totalNum == 100000, "FP32 large: totalNum=100000");
149+ Check(t.blockFactor % 512 == 0, "FP32 large: blockFactor aligned to 512");
150+ Check(t.ubFactor > 0, "FP32 large: ubFactor > 0");
151+ }
152+ 
153+ {
154+ TilingData t;
155+ ComputeTiling(512, 2, 248 * 1024, 28, t);
156+ Check(t.totalNum == 512, "FP16 small: totalNum=512");
157+ Check(t.ubFactor > 0, "FP16 small: ubFactor > 0");
158+ Check(t.ubFactor % 128 == 0, "FP16 small: ubFactor aligned to 128 (256B/2B)");
159+ }
160+ 
161+ {
162+ TilingData t;
163+ ComputeTiling(1, 4, 248 * 1024, 28, t);
164+ Check(t.totalNum == 1, "FP32 scalar: totalNum=1");
165+ Check(t.blockFactor == 512, "FP32 scalar: blockFactor=512 (min aligned)");
166+ }
167+ 
168+ {
169+ TilingData t;
170+ ComputeTiling(0, 4, 248 * 1024, 28, t);
171+ Check(t.totalNum == 0, "Empty tensor: totalNum=0");
172+ }
173+}
174+ 
175+void TestEdgeCases()
176+{
177+ std::cout << "\n=== Edge Case Tests ===" << std::endl;
178+ 
179+ float nan_result = ComputeI1eScalar(std::nanf(""));
180+ Check(std::isnan(nan_result), "i1e(NaN) = NaN");
181+ 
182+ float inf_result = ComputeI1eScalar(INFINITY);
183+ Check(inf_result >= 0.0f && inf_result < 0.01f, "i1e(+Inf) ≈ 0");
184+ 
185+ float neg_inf_result = ComputeI1eScalar(-INFINITY);
186+ Check(neg_inf_result <= 0.0f && neg_inf_result > -0.01f, "i1e(-Inf) ≈ 0");
187+ 
188+ float small = ComputeI1eScalar(0.001f);
189+ Check(fabsf(small - 0.0005f) < 0.001f, "i1e(0.001) ≈ 0.0005 (linear region)");
190+}
191+ 
192+int main()
193+{
194+ std::cout << "========================================" << std::endl;
195+ std::cout << "BesselI1e Unit Tests" << std::endl;
196+ std::cout << "========================================" << std::endl;
197+ 
198+ TestGoldenFunction();
199+ TestTilingComputation();
200+ TestEdgeCases();
201+ 
202+ std::cout << "\n========================================" << std::endl;
203+ std::cout << "Results: " << passed << " passed, " << failed << " failed" << std::endl;
204+ std::cout << "========================================" << std::endl;
205+ 
206+ return failed == 0 ? 0 : 1;
207+}
@@ -71,6 +71,18 @@ do
71 done71 done
72 fi72 fi
73 73 
74+ if [[ ! "$file_path" == "experimental/"* ]]; then
75+ for dir in "${builtin_dirs[@]}"
76+ do
77+ if [[ "$file_path" == *"/$dir/"*"/arch35/"* ]]; then
78+ if [[ ! " ${builtin_ops_name[@]} " =~ " $dir " ]]; then
79+ builtin_ops_name+=("$dir")
80+ fi
81+ break
82+ fi
83+ done
84+ fi
85+ 
74 for dir in "${experimental_dirs[@]}"86 for dir in "${experimental_dirs[@]}"
75 do87 do
76 if [[ "$file_path" == "experimental/"*"/$dir/"*"/arch35/"* ]]; then88 if [[ "$file_path" == "experimental/"*"/$dir/"*"/arch35/"* ]]; then
@@ -119,14 +131,14 @@ execute_run_file() {
119 131 
120if [ ${#builtin_ops_name[@]} -gt 0 ]; then132if [ ${#builtin_ops_name[@]} -gt 0 ]; then
121 builtin_ops_str=$(IFS=,; echo "${builtin_ops_name[*]}")133 builtin_ops_str=$(IFS=,; echo "${builtin_ops_name[*]}")
122- build_cmd="bash build.sh --pkg --ops=$builtin_ops_str --soc=ascend950 -j16 --cann_3rd_lib_path=${ASCEND_3RD_LIB_PATH}"134+ build_cmd="bash build.sh --pkg --ops=${builtin_ops_str} --soc=ascend950 -j16 --cann_3rd_lib_path=${ASCEND_3RD_LIB_PATH}"
123 run_build_command "$build_cmd"135 run_build_command "$build_cmd"
124 execute_run_file "custom"136 execute_run_file "custom"
125fi137fi
126 138 
127if [ ${#experimental_ops_name[@]} -gt 0 ]; then139if [ ${#experimental_ops_name[@]} -gt 0 ]; then
128 experimental_ops_str=$(IFS=,; echo "${experimental_ops_name[*]}")140 experimental_ops_str=$(IFS=,; echo "${experimental_ops_name[*]}")
129- build_cmd="bash build.sh --pkg --experimental --ops=$experimental_ops_str --soc=ascend950 -j16 --cann_3rd_lib_path=${ASCEND_3RD_LIB_PATH}"141+ build_cmd="bash build.sh --pkg --experimental --ops=${experimental_ops_str} --soc=ascend950 -j16 --cann_3rd_lib_path=${ASCEND_3RD_LIB_PATH}"
130 run_build_command "$build_cmd"142 run_build_command "$build_cmd"
131 execute_run_file "custom"143 execute_run_file "custom"
132fi144fi