已合并
【PR】: sync ge_dev to master 20260309 #993
沛洋创建于 3月9日
【PR】: sync ge_dev to master 20260309 #993
已合并
沛洋创建于 3月9日
develop合入到master
78 个文件变更+2613-708
MCMakeLists.txt+3-2
@@ -1,9 +1,9 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
@@ -456,6 +456,7 @@ if (NOT BUILD_OPEN_PROJECT)
456 install(TARGETS gert ge_common ge_common_base ge_executor_shared davinci_executor hybrid_executor ge_runner456 install(TARGETS gert ge_common ge_common_base ge_executor_shared davinci_executor hybrid_executor ge_runner
457 ge_runner_v2 dflow_runner data_flow_base457 ge_runner_v2 dflow_runner data_flow_base
458 ge_compiler aicore_utils slice air_headers458 ge_compiler aicore_utils slice air_headers
459+ om2_executor
459 # 开发环境某些没有下载parser目录460 # 开发环境某些没有下载parser目录
460 # _caffe_parser fmk_onnx_parser fmk_parser parser_common461 # _caffe_parser fmk_onnx_parser fmk_parser parser_common
461 EXPORT air-targets462 EXPORT air-targets
MREADME.md+1-1
@@ -20,7 +20,7 @@ GE 提供对 PyTorch、TensorFlow 前端的友好接入能力,并同时支持
20 20 
21- [构建验证](docs/build.md):介绍组件的完整构建、测试样例运行流程。21- [构建验证](docs/build.md):介绍组件的完整构建、测试样例运行流程。
22- [快速开始](examples/acl/1_sample_resnet50_imagenet_classification/README.md):以 ResNet50 模型为例,介绍如何使用 ATC 工具进行模型转换,并在昇腾 AI 处理器上执行推理。22- [快速开始](examples/acl/1_sample_resnet50_imagenet_classification/README.md):以 ResNet50 模型为例,介绍如何使用 ATC 工具进行模型转换,并在昇腾 AI 处理器上执行推理。
23-- [快速开始-LLM](examples/acl/2_sample_qwen_llm/README.md):以 Qwen 模型为例,介绍如何使用 ATC 工具进行LLM模型转换,并实现LLM模型的加载、执行和获取执行结果等。23+- [快速开始-LLM](examples/acl/3_sample_qwen_llm/README.md):以 Qwen 模型为例,介绍如何使用 ATC 工具进行LLM模型转换,并实现LLM模型的加载、执行和获取执行结果等。
24 24 
25## 📚 文档25## 📚 文档
26 26 
Dapi/acl/acl_cblas/types/op_attr.h+0-90
@@ -1,90 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef ACL_TYPES_OP_ATTR_H_
12-#define ACL_TYPES_OP_ATTR_H_
13- 
14-#include "graph/op_desc.h"
15-#include "graph/utils/attr_utils.h"
16-#include "common/log_inner.h"
17-#include "utils/array_utils.h"
18- 
19-struct ACL_FUNC_VISIBILITY aclopAttr {
20- aclopAttr() = default;
21- aclopAttr(const aclopAttr &opAttr);
22- 
23- ~aclopAttr() = default;
24- 
25- inline const std::map<std::string, ge::GeAttrValue> &Attrs() const
26- {
27- return attrs_;
28- }
29- 
30- inline const std::map<std::string, ge::GeAttrValue> &EmplaceAttr(const std::string &str, ge::GeAttrValue val)
31- {
32- (void)attrs_.emplace(str, val);
33- return attrs_;
34- }
35- 
36- inline void ClearConstBuf()
37- {
38- constDataBuf_.clear();
39- }
40- 
41- inline void EmplaceConstBuf(std::string &str)
42- {
43- constDataBuf_.emplace_back(str);
44- }
45- 
46- inline const std::vector<std::string> &GetConstBuf() const
47- {
48- return constDataBuf_;
49- }
50- 
51- template<typename T>
52- aclError SetAttr(const char_t *const attrName, const T val)
53- {
54- ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(attrName);
55- const auto attrVal = ge::GeAttrValue::CreateFrom<T>(val);
56- attrs_[std::string(attrName)] = attrVal;
57- return ACL_SUCCESS;
58- }
59- 
60- template<typename T>
61- aclError SetAttr(const char_t *const attrName, const int32_t numValues, const T *const values)
62- {
63- ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(attrName);
64- if (numValues > 0) {
65- ACL_REQUIRES_NOT_NULL_WITH_INPUT_REPORT(values);
66- }
67- std::vector<T> valueVec;
68- for (int32_t i = 0; i < numValues; ++i) {
69- valueVec.push_back(values[i]);
70- }
71- 
72- const auto attrValues = ge::GeAttrValue::CreateFrom<std::vector<T>>(valueVec);
73- attrs_[std::string(attrName)] = attrValues;
74- return ACL_SUCCESS;
75- }
76- 
77- void UpdateDigest();
78- 
79- size_t GetDigest() const;
80- 
81- std::string DebugString() const;
82- 
83- bool HasAttr(const char_t *const attrName) const;
84- 
85-private:
86- std::map<std::string, ge::GeAttrValue> attrs_;
87- std::vector<std::string> constDataBuf_;
88- mutable size_t digest_ = 0U;
89-};
90-#endif // ACL_TYPES_OP_ATTR_H_
Mapi/acl/acl_op_compiler/single_op/compile/op_compile_processor.h+1-1
@@ -13,7 +13,7 @@
13 13 
14#include <mutex>14#include <mutex>
15 15 
16-#include "types/acl_op.h"16+#include "types/acl_op_inner.h"
17 17 
18struct aclGraphDumpOption {18struct aclGraphDumpOption {
19 std::string stage;19 std::string stage;
Dapi/acl/acl_op_compiler/single_op/compile/op_compile_service.h+0-60
@@ -1,60 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef ACL_OP_EXEC_COMPILER_OP_COMPILE_SERVICE_H
12-#define ACL_OP_EXEC_COMPILER_OP_COMPILE_SERVICE_H
13- 
14-#include "op_compiler.h"
15- 
16-namespace acl {
17-using CompilerCreator = OpCompiler *(*)();
18- 
19-const int32_t ACL_ERROR_COMPILER_NOT_REGISTERED = 16;
20- 
21-enum CompileStrategy {
22- NO_COMPILER,
23- NATIVE_COMPILER,
24- REMOTE_COMPILER
25-};
26- 
27-class ACL_FUNC_VISIBILITY OpCompileService {
28-public:
29- ~OpCompileService();
30- 
31- static OpCompileService &GetInstance()
32- {
33- static OpCompileService instance;
34- return instance;
35- }
36- 
37- void RegisterCreator(const CompileStrategy strategy, const CompilerCreator creatorFn);
38- 
39- aclError SetCompileStrategy(const CompileStrategy strategy, const std::map<std::string, std::string> &options);
40- 
41- aclError CompileOp(const AclOp &op, std::shared_ptr<void> &modelData, size_t &modelSize) const;
42- 
43- aclError CompileAndDumpGraph(const acl::AclOp &op, const char_t *const graphDumpPath,
44- const aclGraphDumpOption *const dumpOpt) const;
45- 
46-private:
47- OpCompileService() = default;
48- 
49- std::map<CompileStrategy, CompilerCreator> creators_;
50- OpCompiler *compiler_ = nullptr;
51-};
52- 
53-class ACL_FUNC_VISIBILITY OpCompilerRegister {
54-public:
55- OpCompilerRegister(const CompileStrategy strategy, const CompilerCreator creatorFn);
56- ~OpCompilerRegister() = default;
57-};
58-} // namespace acl
59- 
60-#endif // ACL_OP_EXEC_COMPILER_OP_COMPILE_SERVICE_H
Dapi/acl/acl_op_compiler/single_op/compile/op_compiler.h+0-58
@@ -1,58 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef ACL_OP_EXEC_COMPILER_OP_COMPILER_H
12-#define ACL_OP_EXEC_COMPILER_OP_COMPILER_H
13- 
14-#include "acl/acl_op.h"
15-#include "acl/acl_op_compiler.h"
16- 
17-#include "graph/op_desc.h"
18-#include "graph/ge_tensor.h"
19-#include "common/ge_common/ge_types.h"
20- 
21-#include "common/common_inner.h"
22-#include "types/acl_op.h"
23-#include "types/op_model.h"
24- 
25-namespace acl {
26-struct CompileParam {
27- ge::OpDescPtr opDesc;
28- std::vector<ge::GeTensor> inputs;
29- std::vector<ge::GeTensor> outputs;
30- ge::OpEngineType engineType;
31- int32_t compileFlag;
32-};
33- 
34-class OpCompiler {
35-public:
36- OpCompiler() = default;
37- 
38- virtual ~OpCompiler() = default;
39- 
40- virtual aclError Init(const std::map<std::string, std::string> &options) = 0;
41- 
42- aclError CompileOp(const AclOp &op, std::shared_ptr<void> &modelData, size_t &modelSize);
43- 
44- aclError CompileAndDumpGraph(const AclOp &op, const char_t *const graphDumpPath,
45- const aclGraphDumpOption *const dumpOpt);
46- 
47-protected:
48- virtual aclError DoCompile(CompileParam &param, std::shared_ptr<void> &modelData, size_t &modelSize) = 0;
49- 
50- virtual aclError GenGraphAndDump(CompileParam &param, const char_t *const graphDumpPath,
51- const aclGraphDumpOption *const dumpOpt) = 0;
52- 
53-private:
54- static aclError MakeCompileParam(const AclOp &op, CompileParam &param, const int32_t compileFlag);
55-};
56-} // namespace acl
57- 
58-#endif // ACL_OP_EXEC_COMPILER_OP_COMPILER_H
Dapi/acl/acl_op_compiler/single_op/compile/op_kernel_selector.h+0-76
@@ -1,76 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef TRUNK_PROJ_OP_KERNEL_SELECTOR_H
12-#define TRUNK_PROJ_OP_KERNEL_SELECTOR_H
13- 
14-#include <string>
15-#include <vector>
16-#include <map>
17-#include <mutex>
18-#include <climits>
19- 
20-#include "types/acl_op.h"
21-#include "utils/acl_op_map.h"
22-#include "types/op_attr.h"
23- 
24-struct aclopKernelDesc {
25- std::string kernelId;
26- const void *stubFunc = nullptr; // no need for deallocating
27- uint32_t blockDim = 0U;
28- std::vector<size_t> workspaceSizes;
29- std::string extendArgs;
30- uint64_t timestamp = ULLONG_MAX;
31- 
32- std::string opType;
33- std::vector<aclTensorDesc> inputDescArr;
34- std::vector<aclTensorDesc> outputDescArr;
35- uint64_t seq = 0U;
36- aclopAttr opAttr;
37-};
38- 
39-namespace acl {
40-using OpKernelDesc = aclopKernelDesc;
41- 
42-class OpKernelSelector {
43-public:
44- ~OpKernelSelector() = default;
45- static OpKernelSelector &GetInstance()
46- {
47- static OpKernelSelector instance;
48- return instance;
49- }
50- 
51- bool HasSelectFunc(const std::string &opType) const;
52- 
53- bool Register(const std::string &opType, aclopCompileFunc func);
54- 
55- void Unregister(const std::string &opType);
56- 
57- aclError SelectOpKernel(const AclOp &op);
58- 
59- aclError GetOpKernelDesc(const AclOp &op, std::shared_ptr<OpKernelDesc> &desc);
60- 
61- void SetMaxOpNum(const uint64_t maxOpNum);
62- 
63-private:
64- OpKernelSelector();
65- aclopCompileFunc GetSelectFunc(const std::string &opType);
66- 
67- aclError InsertAclop2KernelDesc(const AclOp &op, const std::shared_ptr<OpKernelDesc> &desc) const;
68- 
69- std::mutex mu_;
70- std::map<std::string, aclopCompileFunc> selectors_;
71- 
72- AclOpMap<std::shared_ptr<OpKernelDesc>> kernelDescMap_;
73-};
74-} // namespace acl
75- 
76-#endif // TRUNK_PROJ_OP_KERNEL_SELECTOR_H
Mapi/acl/acl_op_compiler/single_op/op_compiler.cpp+1-1
@@ -15,7 +15,7 @@
15#include "op_executor.h"15#include "op_executor.h"
16#include "acl_op_resource_manager.h"16#include "acl_op_resource_manager.h"
17#include "common/prof_api_reg.h"17#include "common/prof_api_reg.h"
18-#include "types/acl_op.h"18+#include "types/acl_op_inner.h"
19#include "utils/array_utils.h"19#include "utils/array_utils.h"
20#include "acl/acl_rt.h"20#include "acl/acl_rt.h"
21#include "platform/platform_info.h"21#include "platform/platform_info.h"
Dapi/acl/acl_op_compiler/single_op/op_executor.h+0-103
@@ -1,103 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef ACL_OP_EXEC_OP_EXECUTOR_H
12-#define ACL_OP_EXEC_OP_EXECUTOR_H
13- 
14-#include "framework/executor/ge_executor.h"
15- 
16-#include <memory>
17-#include <map>
18-#include <unordered_map>
19-#include <map>
20- 
21-#include "acl/acl_op.h"
22-#include "types/acl_op.h"
23-#include "types/op_model.h"
24-#include "single_op/compile/op_kernel_selector.h"
25-#include "framework/runtime/model_v2_executor.h"
26-#include "framework/runtime/stream_executor.h"
27- 
28-namespace acl {
29-struct OpHandle {
30- std::string opType;
31- int32_t numInputs = 0;
32- int32_t numOutputs = 0;
33- OpModel opModel;
34- std::mutex mutexForStatic;
35- std::unordered_map<aclrtStream, ge::SingleOp *> cachedOperators;
36- std::mutex mutexForDynamic;
37- std::map<aclrtStream, ge::DynamicSingleOp *> cachedDynamicOperators;
38- std::shared_ptr<aclopKernelDesc> kernelDesc;
39- AclOp aclOp;
40- bool isDynamic = false;
41-};
42- 
43- 
44-inline void FixGeDataBuffer(const aclDataBuffer *const aclBuf, const aclMemType memType, ge::DataBuffer &geBuf)
45-{
46- geBuf.data = aclBuf->data;
47- geBuf.length = aclBuf->length;
48- geBuf.placement =
49- ((memType == ACL_MEMTYPE_DEVICE) ? static_cast<uint32_t>(memType) : static_cast<uint32_t>(ACL_MEMTYPE_HOST));
50-}
51- 
52- 
53-class ACL_FUNC_VISIBILITY OpExecutor {
54-public:
55- static aclError CreateOpHandle(const AclOp &aclOp, OpHandle **const handle);
56- 
57- static aclError ExecuteAsync(const AclOp &aclOp,
58- const aclDataBuffer *const inputs[],
59- aclDataBuffer *const outputs[],
60- const aclrtStream stream);
61- 
62- static aclError ExecuteAsync(OpHandle &opHandle,
63- const aclDataBuffer *const inputs[],
64- aclDataBuffer *const outputs[],
65- const aclrtStream stream);
66- 
67-private:
68- static aclError LoadSingleOp(const OpModel &modelInfo, const aclrtStream stream, ge::SingleOp **const singleOp);
69- 
70- static aclError LoadDynamicSingleOp(const OpModel &modelInfo,
71- const aclrtStream stream,
72- ge::DynamicSingleOp **const dynamicSingleOp);
73- 
74- static aclError DoExecuteAsync(ge::DynamicSingleOp *const singleOp,
75- const AclOp &aclOp,
76- const aclDataBuffer *const inputs[],
77- const aclDataBuffer *const outputs[],
78- const bool executeWithExactModel = true);
79- 
80- static aclError DoExecuteAsync(ge::SingleOp *const singleOp,
81- const AclOp &aclOp,
82- const aclDataBuffer *const inputs[],
83- const aclDataBuffer *const outputs[],
84- const bool executeWithExactModel = true);
85- 
86- static aclError DoExecuteRT1(const AclOp &aclOp,
87- const aclDataBuffer *const inputs[],
88- aclDataBuffer *const outputs[],
89- const aclrtStream stream,
90- const OpModel *opModelPtr,
91- const bool isDynamic,
92- const bool isExactModel);
93- 
94- static aclError PrepareRt2Execute(const AclOp &aclOp, OpModel *opModelPtr);
95- 
96- static aclError DoExecuteAsync(std::shared_ptr<gert::StreamExecutor> &streamExecutor,
97- const AclOp &aclOp,
98- const aclrtStream stream,
99- const bool executeWithExactModel = true);
100-};
101-} // namespace acl
102- 
103-#endif // ACL_OP_EXEC_OP_EXECUTOR_H
Dapi/acl/acl_op_compiler/single_op/op_model_cache.h+0-55
@@ -1,55 +0,0 @@
1-/**
2- * Copyright (c) 2025 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- 
11-#ifndef ACL_OP_EXEC_OP_MODEL_CACHE_H_
12-#define ACL_OP_EXEC_OP_MODEL_CACHE_H_
13- 
14-#include <unordered_map>
15-#include <mutex>
16- 
17-#include "types/op_model.h"
18-#include "framework/runtime/model_v2_executor.h"
19-#include "framework/runtime/stream_executor.h"
20- 
21-namespace acl {
22-class OpModelCache {
23-public:
24- OpModelCache() = default;
25- 
26- ~OpModelCache() = default;
27- 
28- aclError GetOpModel(const OpModelDef &modelDef, OpModel &operModel);
29- 
30- std::shared_ptr<std::mutex> GetCacheMutex(const uint64_t id);
31- 
32- aclError Add(const uint64_t opId, OpModel &operModel);
33- 
34- aclError Delete(const OpModelDef &modelDef, const bool isDynamic);
35- 
36- aclError CreateCachedExecutor(std::shared_ptr<gert::StreamExecutor> &streamExecutor, rtStream_t stream,
37- const gert::ModelExecuteArg &arg, gert::ModelV2Executor *&executor);
38- 
39- std::shared_ptr<gert::StreamExecutor> GetRT2Executor(const uint64_t id);
40- 
41- aclError UpdateCachedExecutor(const uint64_t &id, const std::shared_ptr<gert::StreamExecutor> &executor);
42- 
43- aclError UnloadCachedModelData(const uint64_t &id);
44- 
45- aclError CleanCachedExecutor(rtStream_t stream);
46- 
47- void CleanCachedModels() noexcept;
48- 
49-private:
50- std::unordered_map<uint64_t, OpModel> cachedModels_;
51- std::recursive_mutex mutex_;
52-};
53-} // namespace acl
54- 
55-#endif // ACL_OP_EXEC_OP_MODEL_CACHE_H_
Mapi/acl/acl_op_executor/CMakeLists.txt+1-1
@@ -28,7 +28,7 @@ add_library(acl_op_executor_impl SHARED
28 single_op/executor/op_task.cpp28 single_op/executor/op_task.cpp
29 types/op_attr.cpp29 types/op_attr.cpp
30 types/op_model.cpp30 types/op_model.cpp
31- types/acl_op.cpp31+ types/acl_op_inner.cpp
32 ../common/common_inner.cpp32 ../common/common_inner.cpp
33 ../common/log_inner.cpp33 ../common/log_inner.cpp
34 ../common/json_parser.cpp34 ../common/json_parser.cpp
Mapi/acl/acl_op_executor/single_op/acl_op_resource_manager.h+1-1
@@ -22,7 +22,7 @@
22#include "graph/ge_attr_value.h"22#include "graph/ge_attr_value.h"
23#include "mmpa/mmpa_api.h"23#include "mmpa/mmpa_api.h"
24#include "types/op_model.h"24#include "types/op_model.h"
25-#include "types/acl_op.h"25+#include "types/acl_op_inner.h"
26#include "single_op/op_model_cache.h"26#include "single_op/op_model_cache.h"
27#include "single_op/compile/op_compiler.h"27#include "single_op/compile/op_compiler.h"
28#include "utils/acl_op_map.h"28#include "utils/acl_op_map.h"
Mapi/acl/acl_op_executor/single_op/compile/op_compiler.h+1-1
@@ -19,7 +19,7 @@
19#include "common/ge_common/ge_types.h"19#include "common/ge_common/ge_types.h"
20 20 
21#include "common/common_inner.h"21#include "common/common_inner.h"
22-#include "types/acl_op.h"22+#include "types/acl_op_inner.h"
23#include "types/op_model.h"23#include "types/op_model.h"
24 24 
25namespace acl {25namespace acl {
Mapi/acl/acl_op_executor/single_op/compile/op_kernel_selector.h+1-1
@@ -17,7 +17,7 @@
17#include <mutex>17#include <mutex>
18#include <climits>18#include <climits>
19 19 
20-#include "types/acl_op.h"20+#include "types/acl_op_inner.h"
21#include "utils/acl_op_map.h"21#include "utils/acl_op_map.h"
22#include "types/op_attr.h"22#include "types/op_attr.h"
23 23 
Mapi/acl/acl_op_executor/single_op/executor/op_task.h+1-1
@@ -11,7 +11,7 @@
11#ifndef TRUNK_PROJ_OP_TASK_H11#ifndef TRUNK_PROJ_OP_TASK_H
12#define TRUNK_PROJ_OP_TASK_H12#define TRUNK_PROJ_OP_TASK_H
13 13 
14-#include "types/acl_op.h"14+#include "types/acl_op_inner.h"
15 15 
16namespace acl {16namespace acl {
17class OpTask {17class OpTask {
Mapi/acl/acl_op_executor/single_op/executor/stream_executor.h+1-1
@@ -14,7 +14,7 @@
14#include <memory>14#include <memory>
15#include <map>15#include <map>
16 16 
17-#include "types/acl_op.h"17+#include "types/acl_op_inner.h"
18#include "resource_manager.h"18#include "resource_manager.h"
19#include "single_op/compile/op_kernel_selector.h"19#include "single_op/compile/op_kernel_selector.h"
20#include "op_task.h"20#include "op_task.h"
Mapi/acl/acl_op_executor/single_op/op.cpp+1-1
@@ -14,7 +14,7 @@
14#include <fstream>14#include <fstream>
15 15 
16#include "common/log_inner.h"16#include "common/log_inner.h"
17-#include "types/acl_op.h"17+#include "types/acl_op_inner.h"
18#include "op_executor.h"18#include "op_executor.h"
19#include "utils/array_utils.h"19#include "utils/array_utils.h"
20#include "utils/string_utils.h"20#include "utils/string_utils.h"
Mapi/acl/acl_op_executor/single_op/op_executor.cpp+1-1
@@ -11,7 +11,7 @@
11#include "op_executor.h"11#include "op_executor.h"
12#include <graph/debug/ge_attr_define.h>12#include <graph/debug/ge_attr_define.h>
13#include "framework/common/profiling_definitions.h"13#include "framework/common/profiling_definitions.h"
14-#include "types/acl_op.h"14+#include "types/acl_op_inner.h"
15#include "common/log_inner.h"15#include "common/log_inner.h"
16#include "model/acl_resource_manager.h"16#include "model/acl_resource_manager.h"
17#include "single_op/acl_op_resource_manager.h"17#include "single_op/acl_op_resource_manager.h"
Mapi/acl/acl_op_executor/single_op/op_executor.h+1-1
@@ -19,7 +19,7 @@
19#include <map>19#include <map>
20 20 
21#include "acl/acl_op.h"21#include "acl/acl_op.h"
22-#include "types/acl_op.h"22+#include "types/acl_op_inner.h"
23#include "types/op_model.h"23#include "types/op_model.h"
24#include "single_op/compile/op_kernel_selector.h"24#include "single_op/compile/op_kernel_selector.h"
25#include "framework/runtime/model_v2_executor.h"25#include "framework/runtime/model_v2_executor.h"
Mapi/acl/acl_op_executor/single_op/shape_range_utils.h+1-1
@@ -14,7 +14,7 @@
14#include <string>14#include <string>
15#include <vector>15#include <vector>
16#include <unordered_map>16#include <unordered_map>
17-#include "types/acl_op.h"17+#include "types/acl_op_inner.h"
18 18 
19namespace acl {19namespace acl {
20class MmRDLockGuard {20class MmRDLockGuard {
Rapi/acl/acl_op_executor/types/acl_op.cppapi/acl/acl_op_executor/types/acl_op_inner.cpp+1-1
@@ -8,7 +8,7 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#include "acl_op.h"11+#include "acl_op_inner.h"
12#include <sstream>12#include <sstream>
13 13 
14namespace {14namespace {
Rapi/acl/acl_op_executor/types/acl_op.hapi/acl/acl_op_executor/types/acl_op_inner.h+3-3
@@ -8,8 +8,8 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#ifndef ACL_TYPES_ACL_OP_H11+#ifndef ACL_TYPES_ACL_OP_INNER_H
12-#define ACL_TYPES_ACL_OP_H12+#define ACL_TYPES_ACL_OP_INNER_H
13 13 
14#include <string>14#include <string>
15 15 
@@ -68,4 +68,4 @@ public:
68};68};
69} // namespace acl69} // namespace acl
70 70 
71-#endif // ACL_TYPES_ACL_OP_H71+#endif // ACL_TYPES_ACL_OP_INNER_H
Mapi/acl/utils/acl_op_map.h+1-1
@@ -15,7 +15,7 @@
15#include <mutex>15#include <mutex>
16#include <vector>16#include <vector>
17#include <climits>17#include <climits>
18-#include "types/acl_op.h"18+#include "types/acl_op_inner.h"
19#include "utils/attr_utils.h"19#include "utils/attr_utils.h"
20#include "utils/hash_utils.h"20#include "utils/hash_utils.h"
21#include <chrono>21#include <chrono>
Mapi/acl/utils/attr_utils.h+1-1
@@ -19,7 +19,7 @@
19#include "graph/op_desc.h"19#include "graph/op_desc.h"
20#include "utils/string_utils.h"20#include "utils/string_utils.h"
21#include "types/op_attr.h"21#include "types/op_attr.h"
22-#include "types/acl_op.h"22+#include "types/acl_op_inner.h"
23#include "types/op_model.h"23#include "types/op_model.h"
24 24 
25namespace acl {25namespace acl {
Mapi/acl/utils/hash_utils.h+1-1
@@ -14,7 +14,7 @@
14#include "utils/string_utils.h"14#include "utils/string_utils.h"
15#include "utils/attr_utils.h"15#include "utils/attr_utils.h"
16#include "types/op_attr.h"16#include "types/op_attr.h"
17-#include "types/acl_op.h"17+#include "types/acl_op_inner.h"
18#include "common/log_inner.h"18#include "common/log_inner.h"
19 19 
20namespace acl {20namespace acl {
Mcmake/air_headers.cmake+2-2
@@ -1,9 +1,9 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
Mcmake/create_headers.cmake+2-2
@@ -1,9 +1,9 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
Mcmake/generate_es_package.cmake+259-75
@@ -52,6 +52,125 @@ message(STATUS "[add_es_library] Module loaded from: ${_ADD_ES_LIBRARY_CMAKE_DIR
52# 7. 多个 ES 包会自动添加依赖关系,确保共享依赖只构建一次52# 7. 多个 ES 包会自动添加依赖关系,确保共享依赖只构建一次
53# ======================================================================================================================53# ======================================================================================================================
54 54 
55+# ======================================================================================================================
56+# add_custom_command 封装宏
57+#
58+# 统一封装代码生成命令,内部根据 COMBINED_COMMERCIAL_MODE 自动选择模式:
59+# 单次模式(COMBINED_COMMERCIAL_MODE=FALSE):仅执行一次 gen_esb,生成 C++ API
60+# 双次模式(COMBINED_COMMERCIAL_MODE=TRUE): 步骤1 代码生成 + 步骤2 历史原型库归档
61+#
62+# 三处调用点(外部 gen_esb 有依赖 / 外部 gen_esb 无依赖 / 源码 gen_esb)共用此宏,
63+# 仅 gen_esb 路径、LD_LIBRARY_PATH、EXCLUDE_OPS、DEPENDS、COMMENT 不同,由调用方通过参数传入。
64+#
65+# 参数:
66+# _gen_esb_exe gen_esb 可执行路径(字面量或生成器表达式 $<TARGET_FILE:gen_esb>)
67+# _lib_dir LD_LIBRARY_PATH(run 包环境传 ${ASCEND_LIB_DIR},源码环境传空字符串)
68+# _excl_ops 排除算子列表(INTERFACE 库传空字符串,其他传 ${ARG_EXCLUDE_OPS})
69+# _comment COMMENT 说明文字
70+#
71+# 调用前需设置 _COMBINED_MODE_DEPENDS:
72+# 有依赖时:set(_COMBINED_MODE_DEPENDS "DEPENDS;dep1;dep2")
73+# 无依赖时:unset(_COMBINED_MODE_DEPENDS)
74+# ======================================================================================================================
75+macro(_es_add_gen_esb_cmd _gen_esb_exe _lib_dir _excl_ops _comment)
76+ if (COMBINED_COMMERCIAL_MODE)
77+ set(_HIST_STAGE_DIR "${ARG_OUTPUT_PATH}")
78+ if ("${_AUTO_HISTORY_REGISTRY}" STREQUAL "${ARG_OUTPUT_PATH}")
79+ # 首次构建(历史库尚不存在于 CANN 路径):_AUTO_HISTORY_REGISTRY == ARG_OUTPUT_PATH,
80+ set(_PREPOPULATE_STAGING "")
81+ else ()
82+ # 非首次构建:将 CANN 只读历史库内容合并复制到 ARG_OUTPUT_PATH
83+ set(_PREPOPULATE_STAGING
84+ COMMAND ${CMAKE_COMMAND} -E copy_directory "${_AUTO_HISTORY_REGISTRY}" "${ARG_OUTPUT_PATH}"
85+ COMMAND chmod u+w "${ARG_OUTPUT_PATH}/index.json"
86+ )
87+ endif ()
88+ 
89+ add_custom_command(
90+ OUTPUT ${CODE_GEN_FLAG}
91+ COMMAND ${CMAKE_COMMAND} -E echo "Generating ES code (combined commercial mode) for package: ${ARG_ES_LINKABLE_AND_ALL_TARGET}"
92+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_CODE_DIR}
93+ COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_CODE_DIR}
94+ # 步骤1: 代码生成(消费历史原型库,gen_esb 自动选取窗口内历史版本对比)
95+ COMMAND bash ${ES_LOCK_SCRIPT}
96+ ${GEN_CODE_DIR}/.gen.lock
97+ ${_gen_esb_exe}
98+ ${OPP_PROTO_PATH}
99+ ${GEN_CODE_DIR}
100+ ${MODULE_NAME}
101+ "${_lib_dir}"
102+ "${_excl_ops}"
103+ ""
104+ ""
105+ ${HISTORY_REGISTRY_ARG}
106+ ""
107+ ""
108+ # 步骤2: 归档到 ARG_OUTPUT_PATH;若已有历史库则先复制并授权,gen_esb 追加新条目
109+ ${_PREPOPULATE_STAGING}
110+ COMMAND ${CMAKE_COMMAND} -E make_directory "${_HIST_STAGE_DIR}"
111+ COMMAND bash ${ES_LOCK_SCRIPT}
112+ ${_HIST_STAGE_DIR}/.extract.lock
113+ ${_gen_esb_exe}
114+ ${OPP_PROTO_PATH}
115+ ${_HIST_STAGE_DIR}
116+ ${MODULE_NAME}
117+ "${_lib_dir}"
118+ ""
119+ ${EXTRACT_HISTORY_FLAG}
120+ ${RELEASE_VERSION_ARG}
121+ ""
122+ ${RELEASE_DATE_ARG}
123+ ${BRANCH_NAME_ARG}
124+ COMMAND ${CMAKE_COMMAND} -E echo "[ES] Historical prototype library generation completed: ${ARG_OUTPUT_PATH}"
125+ # 步骤3: 动态生成 wrapper 文件的 include 内容
126+ COMMAND ${CMAKE_COMMAND} -P ${GENERATE_WRAPPER_SCRIPT}
127+ COMMAND ${CMAKE_COMMAND} -E touch ${CODE_GEN_FLAG}
128+ ${_COMBINED_MODE_DEPENDS}
129+ COMMENT "${_comment}"
130+ JOB_POOL es_gen_esb_serial
131+ VERBATIM
132+ )
133+ else ()
134+ # 历史库路径有效时:代码生成后将 CANN 历史库内容合并复制到 ARG_OUTPUT_PATH
135+ if (_AUTO_HISTORY_REGISTRY)
136+ set(_COPY_EXISTING_HISTORY
137+ COMMAND ${CMAKE_COMMAND} -E copy_directory "${_AUTO_HISTORY_REGISTRY}" "${ARG_OUTPUT_PATH}"
138+ COMMAND ${CMAKE_COMMAND} -E echo "[ES] Existing history registry copied to output: ${ARG_OUTPUT_PATH}"
139+ )
140+ else ()
141+ set(_COPY_EXISTING_HISTORY "")
142+ endif ()
143+ add_custom_command(
144+ OUTPUT ${CODE_GEN_FLAG}
145+ COMMAND ${CMAKE_COMMAND} -E echo "Generating ES code for package: ${ARG_ES_LINKABLE_AND_ALL_TARGET}"
146+ COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_CODE_DIR}
147+ COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_CODE_DIR}
148+ # 单次代码生成
149+ COMMAND bash ${ES_LOCK_SCRIPT}
150+ ${GEN_CODE_DIR}/.gen.lock
151+ ${_gen_esb_exe}
152+ ${OPP_PROTO_PATH}
153+ ${GEN_CODE_DIR}
154+ ${MODULE_NAME}
155+ "${_lib_dir}"
156+ "${_excl_ops}"
157+ ${CODE_GEN_STEP_EXTRACT_FLAG}
158+ ${RELEASE_VERSION_ARG}
159+ ${HISTORY_REGISTRY_ARG}
160+ ${RELEASE_DATE_ARG}
161+ ${BRANCH_NAME_ARG}
162+ # 版本重复时将现有历史库复制到输出目录
163+ ${_COPY_EXISTING_HISTORY}
164+ COMMAND ${CMAKE_COMMAND} -P ${GENERATE_WRAPPER_SCRIPT}
165+ COMMAND ${CMAKE_COMMAND} -E touch ${CODE_GEN_FLAG}
166+ ${_COMBINED_MODE_DEPENDS}
167+ COMMENT "${_comment}"
168+ JOB_POOL es_gen_esb_serial
169+ VERBATIM
170+ )
171+ endif ()
172+endmacro()
173+ 
55function(_add_es_library_impl)174function(_add_es_library_impl)
56 # 0. 生成辅助 shell 脚本(自包含,无需外部文件)175 # 0. 生成辅助 shell 脚本(自包含,无需外部文件)
57 # 在首次调用时创建 run_gen_esb_with_lock.sh 到构建目录176 # 在首次调用时创建 run_gen_esb_with_lock.sh 到构建目录
@@ -63,7 +182,7 @@ function(_add_es_library_impl)
63# Auto-generated by generate_es_package.cmake182# Auto-generated by generate_es_package.cmake
64# ES code generation wrapper script with detailed logging and flock fallback183# ES code generation wrapper script with detailed logging and flock fallback
65#184#
66-# Args: \$1=lock_file \$2=gen_esb_path \$3=ASCEND_OPP_PATH \$4=output_dir \$5=module_name \$6=LD_LIBRARY_PATH(optional) \$7=EXCLUDE_OPS(optional)185+# Args: \$1=lock_file \$2=gen_esb_path \$3=ASCEND_OPP_PATH \$4=output_dir \$5=module_name \$6=LD_LIBRARY_PATH(optional) \$7=EXCLUDE_OPS(optional) \$8=MODE_ARG(optional, e.g. --es_mode=extract_history) \$9=RELEASE_VERSION(optional) \$10=HISTORY_REGISTRY_ARG(optional) \$11=RELEASE_DATE_ARG(optional) \$12=BRANCH_NAME_ARG(optional)
67 186 
68LOCK_FILE=\"\$1\"187LOCK_FILE=\"\$1\"
69GEN_ESB_EXE=\"\$2\"188GEN_ESB_EXE=\"\$2\"
@@ -72,6 +191,11 @@ OUTPUT_DIR=\"\$4\"
72MODULE_NAME=\"\$5\"191MODULE_NAME=\"\$5\"
73LIB_PATH=\"\${6:-}\"192LIB_PATH=\"\${6:-}\"
74EXCLUDE_OPS=\"\${7:-}\"193EXCLUDE_OPS=\"\${7:-}\"
194+EXTRACT_HISTORY_FLAG=\"\${8:-}\"
195+RELEASE_VERSION_FLAG=\"\${9:-}\"
196+HISTORY_REGISTRY_ARG=\"\${10:-}\"
197+RELEASE_DATE_ARG=\"\${11:-}\"
198+BRANCH_NAME_ARG=\"\${12:-}\"
75 199 
76# Enable pipefail to ensure exit code from gen_esb is captured through pipes200# Enable pipefail to ensure exit code from gen_esb is captured through pipes
77set -o pipefail201set -o pipefail
@@ -152,10 +276,10 @@ execute_gen_esb() {
152 else276 else
153 ENV_PREFIX=\"ASCEND_OPP_PATH=\${OPP_PATH}\"277 ENV_PREFIX=\"ASCEND_OPP_PATH=\${OPP_PATH}\"
154 fi278 fi
155- log_debug \"Command: \$ENV_PREFIX \\\"\${GEN_ESB_EXE}\\\" --output_dir=\\\"\${OUTPUT_DIR}\\\" --module_name=\\\"\${MODULE_NAME}\\\" --exclude_ops=\\\"\${EXCLUDE_OPS}\\\"\"279+ log_debug \"Command: \$ENV_PREFIX \\\"\${GEN_ESB_EXE}\\\" --output_dir=\\\"\${OUTPUT_DIR}\\\" --module_name=\\\"\${MODULE_NAME}\\\" --exclude_ops=\\\"\${EXCLUDE_OPS}\\\" \${EXTRACT_HISTORY_FLAG} \${RELEASE_VERSION_FLAG} \${HISTORY_REGISTRY_ARG} \${RELEASE_DATE_ARG} \${BRANCH_NAME_ARG}\"
156 280 
157 # Execute gen_esb directly (without env -i, with pipefail enabled)281 # Execute gen_esb directly (without env -i, with pipefail enabled)
158- if eval \"\$ENV_PREFIX \\\"\${GEN_ESB_EXE}\\\" --output_dir=\\\"\${OUTPUT_DIR}\\\" --module_name=\\\"\${MODULE_NAME}\\\" --exclude_ops=\\\"\${EXCLUDE_OPS}\\\" 2>&1 | tee -a \\\"\${DEBUG_LOG}\\\"\"; then282+ if eval \"\$ENV_PREFIX \\\"\${GEN_ESB_EXE}\\\" --output_dir=\\\"\${OUTPUT_DIR}\\\" --module_name=\\\"\${MODULE_NAME}\\\" --exclude_ops=\\\"\${EXCLUDE_OPS}\\\" \${EXTRACT_HISTORY_FLAG} \${RELEASE_VERSION_FLAG} \${HISTORY_REGISTRY_ARG} \${RELEASE_DATE_ARG} \${BRANCH_NAME_ARG} 2>&1 | tee -a \\\"\${DEBUG_LOG}\\\"\"; then
159 log_debug \"[Success] gen_esb executed successfully\"283 log_debug \"[Success] gen_esb executed successfully\"
160 return 0284 return 0
161 else285 else
@@ -310,6 +434,54 @@ exit 1
310 message(STATUS "_add_es_library_impl: EXCLUDE_OPS is ${ARG_EXCLUDE_OPS}")434 message(STATUS "_add_es_library_impl: EXCLUDE_OPS is ${ARG_EXCLUDE_OPS}")
311 endif ()435 endif ()
312 436 
437+ # 历史原型库相关参数
438+ # 使用 cmake 变量(-D 传入);若未定义则从同名环境变量捕获。
439+ # GE_ES_EXTRACT_HISTORY: bool 开关,ON 时启用历史原型库归档模式(两次 gen_esb 调用);
440+ # 不设置或 OFF 时走纯代码生成模式(仅生成 C++ API,不归档)
441+ # GE_ES_RELEASE_VERSION: 当前新版本号(例如 "8.0.RC1"),用于历史原型库归档
442+ # GE_ES_RELEASE_DATE: 归档时的发布日期(可选,格式 YYYY-MM-DD,不指定则 gen_esb 使用当前日期)
443+ # GE_ES_BRANCH_NAME: 构建分支名(可选;master 分支自动屏蔽归档参数)
444+ #
445+ # 历史原型库路径由函数内部从 cmake 文件路径自动推导(${CANN_INSTALL_PATH}/cann/opp/history_registry/<module>),
446+ # 路径存在且非空时自动传 --history_registry,无需用户传参。
447+ #
448+ # 从环境变量兜底捕获(cmake 变量未定义时生效)
449+ foreach(_ES_VAR GE_ES_EXTRACT_HISTORY GE_ES_RELEASE_VERSION GE_ES_RELEASE_DATE GE_ES_BRANCH_NAME)
450+ if (NOT DEFINED ${_ES_VAR} AND DEFINED ENV{${_ES_VAR}})
451+ set(${_ES_VAR} "$ENV{${_ES_VAR}}")
452+ message(STATUS "[ES] Captured from environment variable: ${_ES_VAR}=${${_ES_VAR}}")
453+ endif ()
454+ endforeach ()
455+ 
456+ # master 分支:屏蔽全部归档参数,走纯代码生成模式;历史原型库路径仍传递(用于生成带重载 C++ API)
457+ if (GE_ES_BRANCH_NAME STREQUAL "master")
458+ if (GE_ES_EXTRACT_HISTORY OR GE_ES_RELEASE_VERSION OR GE_ES_RELEASE_DATE)
459+ message(STATUS "[ES] Branch is master, ignoring GE_ES_EXTRACT_HISTORY/GE_ES_RELEASE_VERSION/GE_ES_RELEASE_DATE/GE_ES_BRANCH_NAME, using code-generation-only mode")
460+ endif ()
461+ set(GE_ES_EXTRACT_HISTORY OFF)
462+ set(GE_ES_RELEASE_VERSION "")
463+ set(GE_ES_RELEASE_DATE "")
464+ set(GE_ES_BRANCH_NAME "")
465+ endif ()
466+ 
467+ set(EXTRACT_HISTORY_FLAG "")
468+ if (GE_ES_EXTRACT_HISTORY)
469+ set(EXTRACT_HISTORY_FLAG "--es_mode=extract_history")
470+ message(STATUS "[ES] Historical prototype library mode enabled (GE_ES_EXTRACT_HISTORY=ON), gen_esb will append --es_mode=extract_history")
471+ endif ()
472+ set(RELEASE_VERSION_ARG "")
473+ if (GE_ES_RELEASE_VERSION)
474+ set(RELEASE_VERSION_ARG "--release_version=${GE_ES_RELEASE_VERSION}")
475+ endif ()
476+ set(RELEASE_DATE_ARG "")
477+ if (GE_ES_RELEASE_DATE)
478+ set(RELEASE_DATE_ARG "--release_date=${GE_ES_RELEASE_DATE}")
479+ endif ()
480+ set(BRANCH_NAME_ARG "")
481+ if (GE_ES_BRANCH_NAME)
482+ set(BRANCH_NAME_ARG "--branch_name=${GE_ES_BRANCH_NAME}")
483+ endif ()
484+ 
313 # 2.1. 检查 OPP_PROTO_TARGET 是否存在485 # 2.1. 检查 OPP_PROTO_TARGET 是否存在
314 if (NOT TARGET ${ARG_OPP_PROTO_TARGET})486 if (NOT TARGET ${ARG_OPP_PROTO_TARGET})
315 message(FATAL_ERROR "_add_es_library_impl: OPP_PROTO_TARGET '${ARG_OPP_PROTO_TARGET}' is not a valid CMake target")487 message(FATAL_ERROR "_add_es_library_impl: OPP_PROTO_TARGET '${ARG_OPP_PROTO_TARGET}' is not a valid CMake target")
@@ -551,7 +723,72 @@ exit 1
551 723 
552 message(STATUS "add_es_package: Module name for gen_esb: ${MODULE_NAME}")724 message(STATUS "add_es_package: Module name for gen_esb: ${MODULE_NAME}")
553 725 
554- # 2.7. 检测 eager_style_graph_builder_base 的来源726+ # 2.7. 自动推导历史原型库路径
727+ # 从 cmake 文件路径推导安装根目录,查找 ${CANN_INSTALL_PATH}/cann/opp/history_registry/${MODULE_NAME},
728+ # 路径存在且非空时自动传 --history_registry 给 gen_esb,无需用户显式设置。
729+ set(HISTORY_REGISTRY_ARG "")
730+ set(_AUTO_HISTORY_REGISTRY "")
731+ if (USE_EXTERNAL_GEN_ESB)
732+ get_filename_component(_HIST_GE_DIR "${_ADD_ES_LIBRARY_CMAKE_DIR}" DIRECTORY) # 去掉 /cmake
733+ get_filename_component(_HIST_INCLUDE_DIR "${_HIST_GE_DIR}" DIRECTORY) # 去掉 /ge
734+ get_filename_component(_HIST_CANN_DIR "${_HIST_INCLUDE_DIR}" DIRECTORY) # 去掉 /include
735+ set(_CANDIDATE "${_HIST_CANN_DIR}/opp/history_registry/${MODULE_NAME}")
736+ if (IS_DIRECTORY "${_CANDIDATE}")
737+ file(GLOB _HIST_CONTENTS LIST_DIRECTORIES true "${_CANDIDATE}/*")
738+ if (_HIST_CONTENTS)
739+ set(_AUTO_HISTORY_REGISTRY "${_CANDIDATE}")
740+ set(HISTORY_REGISTRY_ARG "--history_registry=${_CANDIDATE}")
741+ message(STATUS "[add_es_library] Auto-detected history registry: ${_CANDIDATE}")
742+ else ()
743+ message(STATUS "[add_es_library] History registry path exists but is empty, skipping: ${_CANDIDATE}")
744+ endif ()
745+ else ()
746+ message(STATUS "[add_es_library] No history registry found at ${_CANDIDATE}, skipping")
747+ endif ()
748+ endif ()
749+ 
750+ # 版本去重:若历史原型库中已存在相同版本号
751+ set(_DUPLICATE_VERSION_DETECTED FALSE)
752+ if (GE_ES_EXTRACT_HISTORY AND GE_ES_RELEASE_VERSION AND _AUTO_HISTORY_REGISTRY)
753+ set(_INDEX_JSON "${_AUTO_HISTORY_REGISTRY}/index.json")
754+ if (EXISTS "${_INDEX_JSON}")
755+ file(READ "${_INDEX_JSON}" _INDEX_CONTENT)
756+ string(FIND "${_INDEX_CONTENT}" "\"${GE_ES_RELEASE_VERSION}\"" _VER_POS)
757+ if (_VER_POS GREATER_EQUAL 0)
758+ message(STATUS "[ES] Version ${GE_ES_RELEASE_VERSION} already exists in historical prototype library, skipping archive, still using code generation mode")
759+ message(STATUS "[ES] Existing history registry will be copied to output: ${ARG_OUTPUT_PATH}")
760+ set(GE_ES_EXTRACT_HISTORY OFF)
761+ set(EXTRACT_HISTORY_FLAG "")
762+ set(_DUPLICATE_VERSION_DETECTED TRUE)
763+ endif ()
764+ endif ()
765+ endif ()
766+ 
767+ # 只要 GE_ES_EXTRACT_HISTORY=ON 就走双次调用路径
768+ # 有已有历史原型库 → codegen(带重载)+ extract&merge
769+ # 无已有历史原型库(首次构建)→ codegen + extract 生成全新历史原型库,输出到 OUTPUT_PATH
770+ set(COMBINED_COMMERCIAL_MODE FALSE)
771+ if (GE_ES_EXTRACT_HISTORY)
772+ set(COMBINED_COMMERCIAL_MODE TRUE)
773+ if (_AUTO_HISTORY_REGISTRY)
774+ message(STATUS " - [add_es_library] Combined commercial mode: "
775+ "code gen with overload + extract & merge history registry (two gen_esb calls internally)")
776+ else ()
777+ set(_AUTO_HISTORY_REGISTRY "${ARG_OUTPUT_PATH}")
778+ message(STATUS " - [add_es_library] Combined commercial mode (first build, no existing history registry): "
779+ "code gen + fresh history registry → ${ARG_OUTPUT_PATH}")
780+ endif ()
781+ endif ()
782+ 
783+ # 代码生成步骤的 --es_mode 参数:
784+ # 完整商发模式下,代码生成步骤不传 --es_mode=extract_history(历史原型库生成模式由第二次 gen_esb 调用完成)
785+ if (COMBINED_COMMERCIAL_MODE)
786+ set(CODE_GEN_STEP_EXTRACT_FLAG "")
787+ else ()
788+ set(CODE_GEN_STEP_EXTRACT_FLAG "${EXTRACT_HISTORY_FLAG}")
789+ endif ()
790+ 
791+ # 2.9. 检测 eager_style_graph_builder_base 的来源
555 set(HAS_ES_BASE_TARGET FALSE)792 set(HAS_ES_BASE_TARGET FALSE)
556 set(ES_BASE_LIB "")793 set(ES_BASE_LIB "")
557 794 
@@ -704,6 +941,7 @@ message(STATUS \"[ES Wrapper] Total operators included: \${NUM_OPS}\")
704 # 然后运行 generate_wrapper.cmake 生成包含所有 #include 的 wrapper 文件941 # 然后运行 generate_wrapper.cmake 生成包含所有 #include 的 wrapper 文件
705 942 
706 set(CODE_GEN_FLAG "${GEN_CODE_DIR}/generated_code.flag")943 set(CODE_GEN_FLAG "${GEN_CODE_DIR}/generated_code.flag")
944+ set(GEN_ESB_OUTPUT_DIR "${GEN_CODE_DIR}")
707 945 
708 # 8.1. 准备依赖列表946 # 8.1. 准备依赖列表
709 # INTERFACE 库不需要构建,不添加到 DEPENDS 中947 # INTERFACE 库不需要构建,不添加到 DEPENDS 中
@@ -716,59 +954,25 @@ message(STATUS \"[ES Wrapper] Total operators included: \${NUM_OPS}\")
716 endif ()954 endif ()
717 endif ()955 endif ()
718 956 
957+ # INTERFACE 库不传 EXCLUDE_OPS(无算子需要排除)
958+ if (TARGET_TYPE STREQUAL "INTERFACE_LIBRARY")
959+ set(_EXCL_OPS_ARG "")
960+ else ()
961+ set(_EXCL_OPS_ARG "${ARG_EXCLUDE_OPS}")
962+ endif ()
963+ 
719 if (USE_EXTERNAL_GEN_ESB)964 if (USE_EXTERNAL_GEN_ESB)
720 # 使用 run 包的 gen_esb965 # 使用 run 包的 gen_esb
721 if (CODE_GEN_DEPENDS)966 if (CODE_GEN_DEPENDS)
722- add_custom_command(967+ set(_COMBINED_MODE_DEPENDS "DEPENDS;${CODE_GEN_DEPENDS}")
723- OUTPUT ${CODE_GEN_FLAG}
724- COMMAND ${CMAKE_COMMAND} -E echo "Generating ES code for package: ${ARG_ES_LINKABLE_AND_ALL_TARGET}"
725- # 清理旧的生成文件(删除整个目录)
726- COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_CODE_DIR}
727- COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_CODE_DIR}
728- # 步骤1: 运行 gen_esb 生成各个算子的 .cpp 文件
729- COMMAND bash ${ES_LOCK_SCRIPT}
730- ${GEN_CODE_DIR}/.gen.lock
731- ${GEN_ESB_EXE}
732- ${OPP_PROTO_PATH}
733- ${GEN_CODE_DIR}
734- ${MODULE_NAME}
735- ${ASCEND_LIB_DIR}
736- ${ARG_EXCLUDE_OPS}
737- # 步骤2: 代码生成完成后,动态生成 wrapper 文件的 include 内容
738- COMMAND ${CMAKE_COMMAND} -P ${GENERATE_WRAPPER_SCRIPT}
739- # 标记完成
740- COMMAND ${CMAKE_COMMAND} -E touch ${CODE_GEN_FLAG}
741- DEPENDS ${CODE_GEN_DEPENDS}
742- COMMENT "Generating ES API code for package '${ARG_ES_LINKABLE_AND_ALL_TARGET}' using run package gen_esb..."
743- JOB_POOL es_gen_esb_serial
744- VERBATIM
745- )
746 else ()968 else ()
747 # INTERFACE 库,无需依赖969 # INTERFACE 库,无需依赖
748- add_custom_command(970+ unset(_COMBINED_MODE_DEPENDS)
749- OUTPUT ${CODE_GEN_FLAG}
750- COMMAND ${CMAKE_COMMAND} -E echo "Generating ES code for package: ${ARG_ES_LINKABLE_AND_ALL_TARGET}"
751- # 清理旧的生成文件(删除整个目录)
752- COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_CODE_DIR}
753- COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_CODE_DIR}
754- # 步骤1: 运行 gen_esb 生成各个算子的 .cpp 文件
755- COMMAND bash ${ES_LOCK_SCRIPT}
756- ${GEN_CODE_DIR}/.gen.lock
757- ${GEN_ESB_EXE}
758- ${OPP_PROTO_PATH}
759- ${GEN_CODE_DIR}
760- ${MODULE_NAME}
761- ${ASCEND_LIB_DIR}
762- ${ARG_EXCLUDE_OPS}
763- # 步骤2: 代码生成完成后,动态生成 wrapper 文件的 include 内容
764- COMMAND ${CMAKE_COMMAND} -P ${GENERATE_WRAPPER_SCRIPT}
765- # 标记完成
766- COMMAND ${CMAKE_COMMAND} -E touch ${CODE_GEN_FLAG}
767- COMMENT "Generating ES API code for package '${ARG_ES_LINKABLE_AND_ALL_TARGET}' using run package gen_esb (no OPP build dependency)..."
768- JOB_POOL es_gen_esb_serial
769- VERBATIM
770- )
771 endif ()971 endif ()
972+ _es_add_gen_esb_cmd(
973+ "${GEN_ESB_EXE}" "${ASCEND_LIB_DIR}" "${_EXCL_OPS_ARG}"
974+ "Generating ES API code for '${ARG_ES_LINKABLE_AND_ALL_TARGET}' using run package gen_esb..."
975+ )
772 else ()976 else ()
773 # 使用源码编译的 gen_esb target977 # 使用源码编译的 gen_esb target
774 # 源码环境的 OPP_PROTO_TARGET 一定是实际的库 target,需要添加依赖978 # 源码环境的 OPP_PROTO_TARGET 一定是实际的库 target,需要添加依赖
@@ -777,30 +981,10 @@ message(STATUS \"[ES Wrapper] Total operators included: \${NUM_OPS}\")
777 if (USE_STANDARD_PATH AND OPP_COPY_FLAG)981 if (USE_STANDARD_PATH AND OPP_COPY_FLAG)
778 list(APPEND CODE_GEN_DEPENDS ${OPP_COPY_FLAG})982 list(APPEND CODE_GEN_DEPENDS ${OPP_COPY_FLAG})
779 endif ()983 endif ()
780- 984+ set(_COMBINED_MODE_DEPENDS "DEPENDS;${CODE_GEN_DEPENDS}")
781- add_custom_command(985+ _es_add_gen_esb_cmd(
782- OUTPUT ${CODE_GEN_FLAG}986+ "$<TARGET_FILE:gen_esb>" "" "${_EXCL_OPS_ARG}"
783- COMMAND ${CMAKE_COMMAND} -E echo "Generating ES code for package: ${ARG_ES_LINKABLE_AND_ALL_TARGET}"987+ "Generating ES API code for '${ARG_ES_LINKABLE_AND_ALL_TARGET}' using source-built gen_esb..."
784- # 清理旧的生成文件(删除整个目录)
785- COMMAND ${CMAKE_COMMAND} -E remove_directory ${GEN_CODE_DIR}
786- COMMAND ${CMAKE_COMMAND} -E make_directory ${GEN_CODE_DIR}
787- # 步骤1: 运行 gen_esb 生成各个算子的 .cpp 文件
788- # 使用包装脚本确保 gen_esb 可靠执行(带文件锁、重试机制和快速检查)
789- COMMAND bash ${ES_LOCK_SCRIPT}
790- ${GEN_CODE_DIR}/.gen.lock
791- $<TARGET_FILE:gen_esb>
792- ${OPP_PROTO_PATH}
793- ${GEN_CODE_DIR}
794- ${MODULE_NAME}
795- ${ARG_EXCLUDE_OPS}
796- # 步骤2: 代码生成完成后,动态生成 wrapper 文件的 include 内容
797- COMMAND ${CMAKE_COMMAND} -P ${GENERATE_WRAPPER_SCRIPT}
798- # 标记完成
799- COMMAND ${CMAKE_COMMAND} -E touch ${CODE_GEN_FLAG}
800- DEPENDS ${CODE_GEN_DEPENDS}
801- COMMENT "Generating ES API code for package '${ARG_ES_LINKABLE_AND_ALL_TARGET}' using source-built gen_esb..."
802- JOB_POOL es_gen_esb_serial
803- VERBATIM
804 )988 )
805 endif ()989 endif ()
806 990 
Mcmake/modules/Findacl_rt.cmake+6-5
@@ -1,11 +1,12 @@
1-# This program is free software, you can redistribute it and/or modify.1+# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").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.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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.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.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10
10if (acl_rt_FOUND)11if (acl_rt_FOUND)
11 message(STATUS "Package acl_rt has been found.")12 message(STATUS "Package acl_rt has been found.")
Mcmake/third_party/build/modules/Findgbenchmark.cmake+3-2
@@ -1,12 +1,13 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
10+ 
10set(BENCHMARK_DIR ${CMAKE_THIRD_PARTY_LIB_DIR})11set(BENCHMARK_DIR ${CMAKE_THIRD_PARTY_LIB_DIR})
11if (TARGET benchmark_build)12if (TARGET benchmark_build)
12 return()13 return()
Mcmake/third_party/build/modules/Findgtest_shared.cmake+2-2
@@ -1,9 +1,9 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
Acompiler/graph/optimize/autofuse/ascir/meta/ascendc_graph_txt_dumper.cpp+1670-0
@@ -0,0 +1,1670 @@
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+ 
11+#include "ascendc_graph_txt_dumper.h"
12+ 
13+#include <sstream>
14+#include <functional>
15+#include <algorithm>
16+#include "graph/utils/type_utils.h"
17+#include "graph/symbolizer/symbolic_utils.h"
18+ 
19+namespace ascir {
20+namespace dumper {
21+// =============================================================================
22+// 工具函数实现
23+// =============================================================================
24+ 
25+/**
26+ * @brief 统一的 Dtype 映射表
27+ */
28+static const std::map<ge::DataType, DtypeInfo> kDtypeInfoMap = {
29+ {ge::DT_FLOAT, {"float32", "f32", "32f"}},
30+ {ge::DT_FLOAT16, {"float16", "f16", "16f"}},
31+ {ge::DT_BF16, {"bfloat16", "bf16", "16f"}},
32+ {ge::DT_INT8, {"int8_t", "i8", "8i"}},
33+ {ge::DT_INT16, {"int16_t", "i16", "16i"}},
34+ {ge::DT_INT32, {"int32_t", "i32", "32i"}},
35+ {ge::DT_INT64, {"int64_t", "i64", "64i"}},
36+ {ge::DT_UINT8, {"uint8_t", "u8", "8u"}},
37+ {ge::DT_UINT16, {"uint16_t", "u16", "16u"}},
38+ {ge::DT_UINT32, {"uint32_t", "u32", "32u"}},
39+ {ge::DT_UINT64, {"uint64_t", "u64", "64u"}},
40+ {ge::DT_BOOL, {"bool", "i1", "1i"}},
41+ {ge::DT_DOUBLE, {"float64", "f64", "64f"}},
42+};
43+ 
44+const DtypeInfo *GetDtypeInfo(ge::DataType dtype) {
45+ auto it = kDtypeInfoMap.find(dtype);
46+ if (it != kDtypeInfoMap.end()) {
47+ return &it->second;
48+ }
49+ return nullptr;
50+}
51+ 
52+int32_t GetAxisTypePriority(ge::Axis::Type type) {
53+ switch (type) {
54+ case ge::Axis::Type::kAxisTypeBlockOuter: return 1;
55+ case ge::Axis::Type::kAxisTypeBlockInner: return 2;
56+ case ge::Axis::Type::kAxisTypeTileOuter: return 3;
57+ case ge::Axis::Type::kAxisTypeTileInner: return 4;
58+ case ge::Axis::Type::kAxisTypeOriginal: return 5;
59+ case ge::Axis::Type::kAxisTypeMerged: return 6;
60+ default: return 999;
61+ }
62+}
63+ 
64+std::string GetAxisTypeSuffix(ge::Axis::Type type) {
65+ switch (type) {
66+ case ge::Axis::Type::kAxisTypeTileOuter: return "TILE_OUT";
67+ case ge::Axis::Type::kAxisTypeBlockOuter: return "BLOCK_OUT";
68+ case ge::Axis::Type::kAxisTypeBlockInner: return "BLOCK_IN";
69+ case ge::Axis::Type::kAxisTypeTileInner: return "TILE_IN";
70+ default: return "";
71+ }
72+}
73+ 
74+std::map<ge::AxisId, std::string> BuildAxisIdToNameMap(const std::vector<ge::AxisPtr> &axes) {
75+ std::map<ge::AxisId, std::string> id_to_name;
76+ for (const auto &axis: axes) {
77+ id_to_name[axis->id] = axis->name;
78+ }
79+ return id_to_name;
80+}
81+ 
82+std::map<int64_t, ge::Axis::Type> BuildAxisIdToTypeMap(const std::vector<ge::AxisPtr> &axes) {
83+ std::map<int64_t, ge::Axis::Type> id_to_type;
84+ for (const auto &axis: axes) {
85+ id_to_type[axis->id] = axis->type;
86+ }
87+ return id_to_type;
88+}
89+ 
90+std::string ExtractDtypeFromTensorType(const std::string &tensor_type) {
91+ // tensor_type 格式: f32[...] 或 float32[...]
92+ size_t pos = tensor_type.find('[');
93+ if (pos != std::string::npos) {
94+ std::string dtype = tensor_type.substr(0, pos);
95+ // 转换简写为完整名称
96+ if (dtype == "f32") return "float32";
97+ if (dtype == "f16") return "float16";
98+ if (dtype == "i32") return "int32";
99+ if (dtype == "i8") return "int8";
100+ if (dtype == "i16") return "int16";
101+ if (dtype == "bf16") return "bfloat16";
102+ return dtype;
103+ }
104+ return tensor_type;
105+}
106+ 
107+std::string ExtractAxisListFromTensorType(const std::string &tensor_type) {
108+ size_t pos = tensor_type.find('[');
109+ if (pos != std::string::npos) {
110+ return tensor_type.substr(pos);
111+ }
112+ return "[]";
113+}
114+ 
115+std::vector<std::string> CollectInputNames(const ascir::Graph &graph, const ge::AscNodePtr &node) {
116+ (void) graph;
117+ std::vector<std::string> input_names;
118+ 
119+ for (uint32_t index = 0U; index < node->GetAllInDataAnchorsSize(); index++) {
120+ auto in_anchor = node->GetInDataAnchor(static_cast<int32_t>(index));
121+ if (in_anchor == nullptr) {
122+ input_names.push_back("nil");
123+ continue;
124+ }
125+ auto peer_out_anchor = in_anchor->GetPeerOutAnchor();
126+ if (peer_out_anchor == nullptr) {
127+ input_names.push_back("nil");
128+ } else {
129+ auto peer_name = peer_out_anchor->GetOwnerNode()->GetName();
130+ int32_t out_idx = peer_out_anchor->GetIdx();
131+ // 检查源节点是否有多个输出,如果有则显示索引
132+ auto peer_node = peer_out_anchor->GetOwnerNode();
133+ if (peer_node && peer_node->GetAllOutDataAnchorsSize() > 1) {
134+ input_names.push_back(peer_name + ".y[" + std::to_string(out_idx) + "]");
135+ } else {
136+ input_names.push_back(peer_name + ".y");
137+ }
138+ }
139+ }
140+ return input_names;
141+}
142+ 
143+SSAMappingInfo BuildSSAMapping(ge::AscNodeVisitor all_nodes) {
144+ SSAMappingInfo info;
145+ size_t topo_id = 0;
146+ 
147+ for (auto node: all_nodes) {
148+ auto node_type = node->GetType();
149+ if (node_type == NodeType::kData) {
150+ info.data_node_names.insert(node->GetName());
151+ } else if (node_type != NodeType::kOutput && node_type != NodeType::kWorkspace) {
152+ info.node_name_to_ssa_id[node->GetName()] = topo_id + 1;
153+ info.node_name_to_topo_id[node->GetName()] = topo_id;
154+ topo_id++;
155+ }
156+ }
157+ 
158+ return info;
159+}
160+ 
161+// =============================================================================
162+// VIEW 1: Loop Execution 内部辅助函数
163+// =============================================================================
164+ 
165+namespace {
166+/**
167+ * @brief 获取 DataType 的字符串表示(完整类型名)
168+ */
169+static std::string GetDtypeString(ge::DataType dtype) {
170+ const DtypeInfo *info = GetDtypeInfo(dtype);
171+ if (info != nullptr) {
172+ return info->full_name;
173+ }
174+ return ge::TypeUtils::DataTypeToSerialString(dtype);
175+}
176+ 
177+// =============================================================================
178+// 向量化相关辅助函数实现
179+// =============================================================================
180+ 
181+/**
182+ * @brief 检查向量化维度是否为广播维度
183+ */
184+bool IsBroadcastDimension(const ge::Expression &stride) {
185+ if (stride.GetExprType() == ge::ExprType::kExprConstantRation) {
186+ int64_t val = 0;
187+ if (stride.GetConstValue(val) && val == 0) {
188+ return true;
189+ }
190+ }
191+ return false;
192+}
193+ 
194+/**
195+ * @brief 获取向量化维度的大小字符串
196+ */
197+std::string GetVectorizedDimSize(const ge::AscTensorAttr &attr,
198+ ge::AxisId axis_id,
199+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
200+ // 找到 axis_id 在 attr.axis 中的位置
201+ size_t found_axis_idx = 0;
202+ for (; found_axis_idx < attr.axis.size(); ++found_axis_idx) {
203+ if (attr.axis[found_axis_idx] == axis_id) {
204+ break;
205+ }
206+ }
207+ 
208+ // 获取对应的 repeat 值
209+ if (found_axis_idx < attr.repeats.size()) {
210+ auto repeat = attr.repeats[found_axis_idx];
211+ if (repeat.GetExprType() == ge::ExprType::kExprConstantRation) {
212+ int64_t val = 0;
213+ if (repeat.GetConstValue(val)) {
214+ return std::to_string(val);
215+ }
216+ return "1";
217+ }
218+ return ge::SymbolicUtils::ToString(repeat);
219+ }
220+ 
221+ // 找不到对应的 repeat,使用轴名
222+ auto it = axis_id_to_name.find(axis_id);
223+ if (it != axis_id_to_name.end()) {
224+ return it->second + "_size";
225+ }
226+ return "1";
227+}
228+ 
229+/**
230+ * @brief 获取 dtype 的简写后缀
231+ */
232+std::string GetDtypeSuffix(ge::DataType dtype) {
233+ const DtypeInfo *info = GetDtypeInfo(dtype);
234+ if (info != nullptr) {
235+ return info->short_name;
236+ }
237+ 
238+ // 未知类型,生成位宽表示
239+ int32_t size_bytes = ge::GetSizeByDataType(dtype);
240+ std::string suffix = (size_bytes > 0) ? std::to_string(size_bytes * 8) : "32";
241+ 
242+ std::string type_name = ge::TypeUtils::DataTypeToSerialString(dtype);
243+ if (type_name.find("UINT") != std::string::npos || type_name.find("uint") != std::string::npos) {
244+ suffix += "u";
245+ } else if (type_name.find("INT") != std::string::npos || type_name.find("int") != std::string::npos ||
246+ type_name.find("BOOL") != std::string::npos) {
247+ suffix += "i";
248+ } else {
249+ suffix += "f";
250+ }
251+ return suffix;
252+}
253+ 
254+/**
255+ * @brief 获取向量化轴的字符串表示
256+ */
257+static std::string GetVectorizedAxesStr(const ascir::Graph &graph, const ge::AscTensorAttr &attr,
258+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
259+ (void) graph;
260+ if (attr.vectorized_axis.empty()) {
261+ return "";
262+ }
263+ 
264+ std::stringstream ss;
265+ ss << "vector<";
266+ 
267+ for (size_t i = 0; i < attr.vectorized_axis.size(); ++i) {
268+ if (i > 0) ss << "x";
269+ 
270+ auto axis_id = attr.vectorized_axis[i];
271+ 
272+ // 检查是否为广播维度
273+ bool is_broadcast = false;
274+ if (i < attr.vectorized_strides.size()) {
275+ is_broadcast = IsBroadcastDimension(attr.vectorized_strides[i]);
276+ }
277+ 
278+ if (is_broadcast) {
279+ ss << "1";
280+ } else {
281+ ss << GetVectorizedDimSize(attr, axis_id, axis_id_to_name);
282+ }
283+ }
284+ 
285+ ss << "x" << GetDtypeSuffix(attr.dtype) << ">";
286+ 
287+ return ss.str();
288+}
289+ 
290+/**
291+ * @brief 获取 tensor 类型字符串(用于函数签名)
292+ */
293+static std::string GetTensorTypeStr(const ascir::Graph &graph, const ge::AscTensorAttr &attr,
294+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
295+ (void) graph;
296+ std::stringstream ss;
297+ 
298+ // 数据类型 - 使用简写类型名
299+ auto dtype = attr.dtype;
300+ std::string dtype_str;
301+ const DtypeInfo *info = GetDtypeInfo(dtype);
302+ if (info != nullptr) {
303+ dtype_str = info->short_name;
304+ } else {
305+ // 使用完整类型名
306+ dtype_str = GetDtypeString(dtype);
307+ }
308+ 
309+ ss << dtype_str << "[";
310+ 
311+ // 形状
312+ for (size_t i = 0; i < attr.axis.size(); ++i) {
313+ if (i > 0) ss << ",";
314+ auto axis_id = attr.axis[i];
315+ 
316+ // 如果是 repeats,输出大小
317+ if (i < attr.repeats.size()) {
318+ auto repeat = attr.repeats[i];
319+ if (repeat.GetExprType() == ge::ExprType::kExprConstantRation) {
320+ int64_t val = 0;
321+ if (repeat.GetConstValue(val)) {
322+ ss << val;
323+ } else {
324+ auto it = axis_id_to_name.find(axis_id);
325+ ss << (it != axis_id_to_name.end() ? it->second : "axis") << "_size";
326+ }
327+ } else {
328+ ss << ge::SymbolicUtils::ToString(repeat);
329+ }
330+ } else {
331+ auto it = axis_id_to_name.find(axis_id);
332+ ss << (it != axis_id_to_name.end() ? it->second : "axis") << "_size";
333+ }
334+ }
335+ 
336+ ss << "]";
337+ return ss.str();
338+}
339+ 
340+/**
341+ * @brief 格式化输入参数列表
342+ */
343+static std::string FormatInputParams(const std::vector<std::string> &input_names,
344+ const SSAMappingInfo &ssa_info) {
345+ std::stringstream ss;
346+ for (size_t i = 0; i < input_names.size(); ++i) {
347+ if (i > 0) ss << ", ";
348+ if (input_names[i] != "nil") {
349+ std::string input_name = input_names[i];
350+ // 去掉 .y 或 .y[index] 后缀
351+ size_t pos = input_name.find(".y");
352+ if (pos != std::string::npos) {
353+ input_name = input_name.substr(0, pos);
354+ }
355+ 
356+ // 判断是 Data 节点还是中间节点
357+ if (ssa_info.IsDataNode(input_name)) {
358+ // Data 节点,使用节点名称
359+ ss << "%" << input_name;
360+ } else {
361+ // 中间节点,使用 SSA 编号
362+ size_t ssa_id = ssa_info.GetSsaId(input_name);
363+ if (ssa_id > 0) {
364+ ss << "%" << ssa_id;
365+ } else {
366+ ss << "%" << input_name;
367+ }
368+ }
369+ }
370+ }
371+ return ss.str();
372+}
373+ 
374+/**
375+ * @brief 收集并排序子图的 loop_axis
376+ */
377+static std::vector<int64_t> CollectSubgraphLoopAxes(const ascir::Graph &graph,
378+ const std::map<int64_t, ge::Axis::Type> &axis_id_to_type) {
379+ auto all_nodes = graph.GetAllNodes();
380+ 
381+ // 收集所有节点的 loop_axis(去重)
382+ std::vector<int64_t> loop_axes_in_order;
383+ std::set<int64_t> seen_loop_axes;
384+ 
385+ for (auto node: all_nodes) {
386+ auto node_type = node->GetType();
387+ if (node_type == NodeType::kData || node_type == NodeType::kOutput || node_type == NodeType::kWorkspace) {
388+ continue;
389+ }
390+ auto loop_axis = node->attr.sched.loop_axis;
391+ if (loop_axis != kInvalidLoopAxis && seen_loop_axes.find(loop_axis) == seen_loop_axes.end()) {
392+ seen_loop_axes.insert(loop_axis);
393+ loop_axes_in_order.push_back(loop_axis);
394+ }
395+ }
396+ 
397+ // 按轴类型排序
398+ std::sort(loop_axes_in_order.begin(), loop_axes_in_order.end(),
399+ [&axis_id_to_type](int64_t a, int64_t b) {
400+ int32_t priority_a = GetAxisTypePriority(axis_id_to_type.at(a));
401+ int32_t priority_b = GetAxisTypePriority(axis_id_to_type.at(b));
402+ if (priority_a != priority_b) {
403+ return priority_a < priority_b;
404+ }
405+ return a < b;
406+ });
407+ 
408+ return loop_axes_in_order;
409+}
410+ 
411+/**
412+ * @brief 按 loop_axis 分组节点
413+ */
414+static std::map<int64_t, std::vector<ge::AscNodePtr> > GroupNodesByLoopAxis(const ascir::Graph &graph) {
415+ std::map<int64_t, std::vector<ge::AscNodePtr> > nodes_by_loop_axis;
416+ auto all_nodes = graph.GetAllNodes();
417+ 
418+ for (auto node: all_nodes) {
419+ auto node_type = node->GetType();
420+ if (node_type == NodeType::kData || node_type == NodeType::kOutput || node_type == NodeType::kWorkspace) {
421+ continue;
422+ }
423+ auto loop_axis = node->attr.sched.loop_axis;
424+ nodes_by_loop_axis[loop_axis].push_back(node);
425+ }
426+ 
427+ return nodes_by_loop_axis;
428+}
429+ 
430+/**
431+ * @brief 输出子图中的单个节点
432+ */
433+static void DumpSubgraphNode(std::stringstream &ss,
434+ const ascir::Graph &graph,
435+ const ge::AscNodePtr &node,
436+ const SSAMappingInfo &ssa_info,
437+ size_t indent) {
438+ std::string node_name = node->GetName();
439+ size_t topo_id = ssa_info.GetTopoId(node_name);
440+ auto node_type = node->GetType();
441+ 
442+ ss << std::string(indent, ' ') << "%" << (topo_id + 1)
443+ << " = ascir.ops." << node_type << "(";
444+ 
445+ // 输入参数
446+ auto input_names = CollectInputNames(graph, node);
447+ ss << FormatInputParams(input_names, ssa_info);
448+ 
449+ ss << ")";
450+ 
451+ // 子图显示标量类型
452+ if (!node->outputs().empty()) {
453+ auto &output_attr = node->outputs()[0]->attr;
454+ ss << " → " << GetDtypeString(output_attr.dtype);
455+ }
456+ 
457+ ss << " # @" << node_name << " (topo_id=" << topo_id << ")" << std::endl;
458+}
459+ 
460+/**
461+ * @brief 输出嵌套循环中的节点
462+ */
463+static void DumpNodesInLoops(std::stringstream &ss,
464+ const ascir::Graph &graph,
465+ const std::vector<int64_t> &loop_axes_in_order,
466+ const std::map<int64_t, std::vector<ge::AscNodePtr> > &nodes_by_loop_axis,
467+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
468+ const SSAMappingInfo &ssa_info) {
469+ std::set<int64_t> opened_loops;
470+ size_t current_depth = 0;
471+ 
472+ for (auto axis_id: loop_axes_in_order) {
473+ // 打开循环
474+ ss << std::string(current_depth * kIndentSpaces, ' ')
475+ << "for %" << axis_id_to_name.at(axis_id) << " in " << axis_id_to_name.at(axis_id) << "_size {" << std::endl;
476+ opened_loops.insert(axis_id);
477+ current_depth++;
478+ 
479+ // 输出 loop_axis = 当前轴的节点
480+ if (nodes_by_loop_axis.count(axis_id) > 0) {
481+ for (auto node: nodes_by_loop_axis.at(axis_id)) {
482+ DumpSubgraphNode(ss, graph, node, ssa_info, current_depth * kIndentSpaces);
483+ }
484+ }
485+ }
486+ 
487+ // 闭合所有循环
488+ for (size_t i = 0; i < loop_axes_in_order.size(); ++i) {
489+ current_depth--;
490+ ss << std::string(current_depth * kIndentSpaces, ' ') << "}" << std::endl;
491+ }
492+}
493+ 
494+/**
495+ * @brief 输出外层节点(loop_axis = kInvalidLoopAxis)
496+ */
497+static void DumpOuterNodes(std::stringstream &ss,
498+ const ascir::Graph &graph,
499+ const std::map<int64_t, std::vector<ge::AscNodePtr> > &nodes_by_loop_axis,
500+ const SSAMappingInfo &ssa_info) {
501+ if (nodes_by_loop_axis.count(kInvalidLoopAxis) == 0) {
502+ return;
503+ }
504+ 
505+ for (auto node: nodes_by_loop_axis.at(kInvalidLoopAxis)) {
506+ DumpSubgraphNode(ss, graph, node, ssa_info, 2); // 2空格缩进
507+ }
508+}
509+ 
510+/**
511+ * @brief 生成子图模式的循环执行视图
512+ */
513+static std::string DumpSubgraphLoopExecution(const ascir::Graph &graph,
514+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
515+ const std::map<int64_t, ge::Axis::Type> &axis_id_to_type) {
516+ std::stringstream ss;
517+ 
518+ auto all_nodes = graph.GetAllNodes();
519+ SSAMappingInfo ssa_info = BuildSSAMapping(all_nodes);
520+ 
521+ // 收集并排序 loop_axis
522+ auto loop_axes_in_order = CollectSubgraphLoopAxes(graph, axis_id_to_type);
523+ 
524+ // 按 loop_axis 分组节点
525+ auto nodes_by_loop_axis = GroupNodesByLoopAxis(graph);
526+ 
527+ // 生成嵌套循环并输出节点
528+ DumpNodesInLoops(ss, graph, loop_axes_in_order, nodes_by_loop_axis, axis_id_to_name, ssa_info);
529+ 
530+ // 输出外层节点
531+ DumpOuterNodes(ss, graph, nodes_by_loop_axis, ssa_info);
532+ 
533+ return ss.str();
534+}
535+} // namespace
536+ 
537+// =============================================================================
538+// VIEW 1: Loop Execution 辅助函数实现
539+// =============================================================================
540+ 
541+namespace {
542+/**
543+ * @brief 检测图是否为子图
544+ */
545+bool IsSubgraph(const std::string &graph_name) {
546+ return (graph_name.find("_VfSubgraph_") != std::string::npos ||
547+ graph_name.find("_Subgraph_") != std::string::npos);
548+}
549+ 
550+/**
551+ * @brief 收集所有 Data 和 Output 节点
552+ */
553+void CollectDataAndOutputNodes(const ascir::Graph &graph,
554+ std::vector<ParamInfo> &inputs,
555+ std::vector<ParamInfo> &outputs,
556+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
557+ auto all_nodes = graph.GetAllNodes();
558+ 
559+ for (auto node: all_nodes) {
560+ auto node_type = node->GetType();
561+ if (node_type == NodeType::kData || node_type == NodeType::kWorkspace) {
562+ if (!node->outputs().empty()) {
563+ auto &output_attr = node->outputs()[0]->attr;
564+ inputs.push_back({node->GetName(), GetTensorTypeStr(graph, output_attr, axis_id_to_name)});
565+ }
566+ } else if (node_type == NodeType::kOutput) {
567+ if (!node->outputs().empty()) {
568+ auto &output_attr = node->outputs()[0]->attr;
569+ outputs.push_back({node->GetName(), GetTensorTypeStr(graph, output_attr, axis_id_to_name)});
570+ }
571+ }
572+ }
573+}
574+ 
575+/**
576+ * @brief 收集所有被向量化的轴
577+ */
578+std::set<int64_t> CollectVectorizedAxes(const ascir::Graph &graph) {
579+ std::set<int64_t> vectorized_axes;
580+ auto all_nodes = graph.GetAllNodes();
581+ 
582+ for (auto node: all_nodes) {
583+ auto node_type = node->GetType();
584+ if (node_type == NodeType::kData || node_type == NodeType::kOutput) {
585+ continue;
586+ }
587+ if (!node->outputs().empty()) {
588+ auto &output_attr = node->outputs()[0]->attr;
589+ for (auto axis_id: output_attr.vectorized_axis) {
590+ vectorized_axes.insert(axis_id);
591+ }
592+ }
593+ }
594+ 
595+ return vectorized_axes;
596+}
597+ 
598+/**
599+ * @brief 生成原始 tensor 形状的注释
600+ */
601+std::string GenerateOriginalShapesComment(const std::vector<ParamInfo> &inputs,
602+ const std::vector<ParamInfo> &outputs) {
603+ std::stringstream ss;
604+ 
605+ ss << "# Original tensor shapes:" << std::endl;
606+ 
607+ if (!inputs.empty()) {
608+ // 按类型分组输入
609+ std::map<std::string, std::vector<std::string> > inputs_by_type;
610+ for (auto &input: inputs) {
611+ auto dtype = ExtractDtypeFromTensorType(input.type);
612+ auto axes = ExtractAxisListFromTensorType(input.type);
613+ std::string full_type = dtype + axes;
614+ inputs_by_type[full_type].push_back(input.name);
615+ }
616+ 
617+ for (auto &entry: inputs_by_type) {
618+ ss << "# ";
619+ for (size_t i = 0; i < entry.second.size(); ++i) {
620+ if (i > 0) ss << ", ";
621+ ss << entry.second[i];
622+ }
623+ ss << ": " << ExtractDtypeFromTensorType(entry.first)
624+ << ExtractAxisListFromTensorType(entry.first) << std::endl;
625+ }
626+ }
627+ 
628+ if (!outputs.empty()) {
629+ for (size_t i = 0; i < outputs.size(); ++i) {
630+ ss << "# output: " << outputs[i].name << ": "
631+ << ExtractDtypeFromTensorType(outputs[i].type) << "[]" << std::endl;
632+ }
633+ }
634+ 
635+ ss << "#" << std::endl;
636+ 
637+ return ss.str();
638+}
639+ 
640+/**
641+ * @brief 构建 Tile/Block 分解树
642+ */
643+AxisTreeNode BuildAxisDecompositionTree(const ge::AxisPtr &axis,
644+ const std::vector<ge::AxisPtr> &all_axis,
645+ const std::set<int64_t> &merged_axes) {
646+ AxisTreeNode node;
647+ node.axis = axis;
648+ node.is_merge = (merged_axes.count(axis->id) > 0);
649+ 
650+ // 找到所有直接从 axis 分解或合并出来的轴
651+ std::vector<ge::AxisPtr> direct_derived;
652+ for (auto &target_axis: all_axis) {
653+ if (target_axis->id == axis->id) {
654+ continue;
655+ }
656+ if (!target_axis->from.empty()) {
657+ bool is_child = false;
658+ for (auto from_id: target_axis->from) {
659+ if (from_id == axis->id) {
660+ is_child = true;
661+ break;
662+ }
663+ }
664+ if (is_child) {
665+ direct_derived.push_back(target_axis);
666+ }
667+ }
668+ }
669+ 
670+ // 按类型排序
671+ std::sort(direct_derived.begin(), direct_derived.end(),
672+ [](const ge::AxisPtr &a, const ge::AxisPtr &b) {
673+ return GetAxisTypePriority(a->type) < GetAxisTypePriority(b->type);
674+ });
675+ 
676+ // 递归构建子树
677+ for (auto &derived: direct_derived) {
678+ node.children.push_back(BuildAxisDecompositionTree(derived, all_axis, merged_axes));
679+ }
680+ 
681+ return node;
682+}
683+ 
684+/**
685+ * @brief 输出 Tile/Block 分解树(递归)
686+ */
687+void PrintAxisDecompositionTree(std::stringstream &ss,
688+ const AxisTreeNode &node,
689+ const std::string &prefix,
690+ const std::string &child_prefix) {
691+ ss << "# " << prefix << node.axis->name;
692+ 
693+ if (node.children.empty()) {
694+ if (node.is_merge) {
695+ ss << " ⋈";
696+ }
697+ ss << std::endl;
698+ return;
699+ }
700+ 
701+ // 判断是否是合并操作
702+ if (node.is_merge) {
703+ ss << "-⋈" << std::endl;
704+ } else {
705+ ss << "-" << std::endl;
706+ }
707+ 
708+ for (size_t i = 0; i < node.children.size(); ++i) {
709+ bool is_last = (i == node.children.size() - 1);
710+ std::string connector = is_last ? "└->" : "┬->";
711+ std::string next_prefix = child_prefix + " " + connector;
712+ std::string next_child_prefix = child_prefix + (is_last ? " " : "│ ");
713+ PrintAxisDecompositionTree(ss, node.children[i], next_prefix, next_child_prefix);
714+ }
715+}
716+ 
717+/**
718+ * @brief 生成 Tile/Block 分解的注释
719+ */
720+std::string GenerateTileBlockDecompositionComment(const std::vector<ge::AxisPtr> &all_axis) {
721+ std::stringstream ss;
722+ ss << "# Tile/Block decomposition:" << std::endl;
723+ 
724+ // 收集所有涉及合并的轴
725+ std::set<int64_t> merged_axes;
726+ for (auto &axis: all_axis) {
727+ if (!axis->from.empty() && axis->from.size() > 1) {
728+ merged_axes.insert(axis->id);
729+ }
730+ }
731+ 
732+ // 构建分解树并按树状图输出
733+ for (auto &axis: all_axis) {
734+ if (axis->type == ge::Axis::Type::kAxisTypeOriginal) {
735+ AxisTreeNode root = BuildAxisDecompositionTree(axis, all_axis, merged_axes);
736+ if (root.children.empty()) {
737+ ss << "# " << axis->name << ": original (no tiling)" << std::endl;
738+ continue;
739+ }
740+ 
741+ PrintAxisDecompositionTree(ss, root, "", "");
742+ }
743+ }
744+ 
745+ ss << "#" << std::endl;
746+ 
747+ return ss.str();
748+}
749+ 
750+/**
751+ * @brief 生成函数签名
752+ */
753+std::string GenerateFunctionSignature(const std::string &graph_name,
754+ const std::vector<ParamInfo> &inputs,
755+ const std::vector<ParamInfo> &outputs) {
756+ std::stringstream ss;
757+ 
758+ ss << "func @" << graph_name << "(";
759+ for (size_t i = 0; i < inputs.size(); ++i) {
760+ if (i > 0) ss << ", ";
761+ ss << "%" << inputs[i].name << ": " << inputs[i].type;
762+ }
763+ 
764+ ss << ") -> ";
765+ if (!outputs.empty()) {
766+ if (outputs.size() > 1) {
767+ ss << "(";
768+ for (size_t i = 0; i < outputs.size(); ++i) {
769+ if (i > 0) ss << ", ";
770+ ss << ExtractDtypeFromTensorType(outputs[i].type) << "[]";
771+ }
772+ ss << ")";
773+ } else {
774+ ss << ExtractDtypeFromTensorType(outputs[0].type) << "[]";
775+ }
776+ } else {
777+ ss << "()";
778+ }
779+ 
780+ ss << " {" << std::endl;
781+ 
782+ return ss.str();
783+}
784+ 
785+/**
786+ * @brief 检查是否有节点设置了 loop_axis
787+ */
788+bool HasLoopAxis(const ascir::Graph &graph) {
789+ auto all_nodes = graph.GetAllNodes();
790+ 
791+ for (auto node: all_nodes) {
792+ auto node_type = node->GetType();
793+ if (node_type == NodeType::kData || node_type == NodeType::kOutput) {
794+ continue;
795+ }
796+ auto loop_axis = node->attr.sched.loop_axis;
797+ if (loop_axis != kInvalidLoopAxis) {
798+ return true;
799+ }
800+ }
801+ 
802+ return false;
803+}
804+ 
805+/**
806+ * @brief 收集所有需要循环的轴
807+ */
808+/**
809+ * @brief 收集有 loop_axis 时的循环轴
810+ */
811+static void CollectLoopAxesWithLoopAxis(const ascir::Graph &graph,
812+ const std::set<int64_t> &vectorized_axes,
813+ std::set<int64_t> &all_loop_axes) {
814+ auto all_nodes = graph.GetAllNodes();
815+ 
816+ for (auto node: all_nodes) {
817+ auto node_type = node->GetType();
818+ if (node_type == NodeType::kData || node_type == NodeType::kOutput) {
819+ continue;
820+ }
821+ 
822+ auto loop_axis = node->attr.sched.loop_axis;
823+ if (loop_axis != kInvalidLoopAxis) {
824+ auto &axis_list = node->attr.sched.axis;
825+ for (auto axis_id: axis_list) {
826+ if (axis_id == loop_axis) {
827+ break; // 到 loop_axis 为止
828+ }
829+ if (vectorized_axes.count(axis_id) == 0) {
830+ all_loop_axes.insert(axis_id);
831+ }
832+ }
833+ if (vectorized_axes.count(loop_axis) == 0) {
834+ all_loop_axes.insert(loop_axis);
835+ }
836+ }
837+ }
838+}
839+ 
840+/**
841+ * @brief 收集无 loop_axis 时的循环轴
842+ */
843+static void CollectLoopAxesWithoutLoopAxis(const ascir::Graph &graph,
844+ const std::set<int64_t> &vectorized_axes,
845+ std::set<int64_t> &all_loop_axes) {
846+ auto all_nodes = graph.GetAllNodes();
847+ 
848+ for (auto node: all_nodes) {
849+ auto node_type = node->GetType();
850+ if (node_type == NodeType::kData || node_type == NodeType::kOutput) {
851+ continue;
852+ }
853+ 
854+ auto &axis_list = node->attr.sched.axis;
855+ for (auto axis_id: axis_list) {
856+ if (vectorized_axes.count(axis_id) == 0) {
857+ all_loop_axes.insert(axis_id);
858+ }
859+ }
860+ }
861+}
862+ 
863+/**
864+ * @brief 按轴类型优先级排序循环轴
865+ */
866+static std::vector<int64_t> SortLoopAxesByPriority(const std::set<int64_t> &all_loop_axes,
867+ const std::map<int64_t, ge::Axis::Type> &axis_id_to_type) {
868+ std::vector<int64_t> sorted_loop_axes(all_loop_axes.begin(), all_loop_axes.end());
869+ std::sort(sorted_loop_axes.begin(), sorted_loop_axes.end(),
870+ [&axis_id_to_type](int64_t a, int64_t b) {
871+ int32_t priority_a = GetAxisTypePriority(axis_id_to_type.at(a));
872+ int32_t priority_b = GetAxisTypePriority(axis_id_to_type.at(b));
873+ if (priority_a != priority_b) {
874+ return priority_a < priority_b;
875+ }
876+ return a < b;
877+ });
878+ return sorted_loop_axes;
879+}
880+ 
881+/**
882+ * @brief 收集所有需要循环的轴
883+ */
884+std::vector<int64_t> CollectLoopAxes(const ascir::Graph &graph,
885+ const std::set<int64_t> &vectorized_axes,
886+ const std::map<int64_t, ge::Axis::Type> &axis_id_to_type) {
887+ std::set<int64_t> all_loop_axes;
888+ bool has_loop_axis = HasLoopAxis(graph);
889+ if (has_loop_axis) {
890+ CollectLoopAxesWithLoopAxis(graph, vectorized_axes, all_loop_axes);
891+ } else {
892+ CollectLoopAxesWithoutLoopAxis(graph, vectorized_axes, all_loop_axes);
893+ }
894+ 
895+ return SortLoopAxesByPriority(all_loop_axes, axis_id_to_type);
896+}
897+ 
898+/**
899+ * @brief 输出 Scalar 节点
900+ */
901+void DumpScalarNode(std::stringstream &ss,
902+ const ge::AscNodePtr &node,
903+ size_t indent_spaces,
904+ size_t topo_id) {
905+ ss << std::string(indent_spaces, ' ') << "%" << (topo_id + 1) << " = ";
906+ 
907+ if (node->attr.ir_attr != nullptr) {
908+ std::string scalar_value;
909+ if (node->attr.ir_attr->GetAttrValue("value", scalar_value) == ge::GRAPH_SUCCESS) {
910+ ss << scalar_value << "f";
911+ } else {
912+ ss << "0.0f";
913+ }
914+ } else {
915+ ss << "0.0f";
916+ }
917+ 
918+ ss << " # @" << node->GetName() << " (topo_id=" << topo_id << ")" << std::endl;
919+}
920+ 
921+/**
922+ * @brief 输出单个节点的执行语句
923+ */
924+void DumpNodeExecution(std::stringstream &ss,
925+ const ascir::Graph &graph,
926+ const ge::AscNodePtr &node,
927+ const SSAMappingInfo &ssa_info,
928+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
929+ size_t indent_spaces) {
930+ std::string node_name = node->GetName();
931+ auto node_type = node->GetType();
932+ size_t topo_id = ssa_info.GetTopoId(node_name);
933+ 
934+ // Scalar 节点特殊处理
935+ if (node_type == NodeType::kScalar) {
936+ DumpScalarNode(ss, node, indent_spaces, topo_id);
937+ return;
938+ }
939+ 
940+ // 非Scalar节点的通用处理
941+ ss << std::string(indent_spaces, ' ') << "%" << (topo_id + 1)
942+ << " = ascir.ops." << node_type << "(";
943+ 
944+ // 输入参数
945+ auto input_names = CollectInputNames(graph, node);
946+ ss << FormatInputParams(input_names, ssa_info);
947+ 
948+ ss << ")";
949+ 
950+ // 类型转换
951+ if (!node->outputs().empty()) {
952+ auto &output_attr = node->outputs()[0]->attr;
953+ auto vectorized_str = GetVectorizedAxesStr(graph, output_attr, axis_id_to_name);
954+ if (!vectorized_str.empty()) {
955+ ss << " → " << vectorized_str;
956+ } else {
957+ ss << " → " << GetDtypeString(output_attr.dtype);
958+ }
959+ }
960+ 
961+ ss << " # @" << node_name << " (topo_id=" << topo_id << ")" << std::endl;
962+}
963+ 
964+/**
965+ * @brief 确定节点应该放置的循环深度
966+ * @param node 节点对象
967+ * @param has_loop_axis 图是否有 loop_axis
968+ * @param loop_axis_to_depth loop_axis 到深度的映射
969+ * @param sorted_loop_axes_size 排序后的 loop_axes 数量
970+ * @param current_depth 当前深度
971+ * @return 目标深度
972+ */
973+static size_t DetermineNodeTargetDepth(const ge::AscNodePtr &node,
974+ bool has_loop_axis,
975+ const std::map<int64_t, size_t> &loop_axis_to_depth,
976+ size_t sorted_loop_axes_size,
977+ size_t current_depth) {
978+ auto node_type = node->GetType();
979+ auto loop_axis = node->attr.sched.loop_axis;
980+ bool is_scalar = (node_type == NodeType::kScalar);
981+ 
982+ if (is_scalar) {
983+ return current_depth;
984+ } else if (has_loop_axis && loop_axis != kInvalidLoopAxis && loop_axis_to_depth.count(loop_axis) > 0) {
985+ return loop_axis_to_depth.at(loop_axis);
986+ } else if (!has_loop_axis) {
987+ return sorted_loop_axes_size;
988+ }
989+ return 0;
990+}
991+ 
992+/**
993+ * @brief 关闭不需要的循环
994+ * @param ss 输出流
995+ * @param current_depth 当前深度(会被修改)
996+ * @param target_depth 目标深度
997+ * @param opened_loops 已打开的循环集合(会被修改)
998+ */
999+static void CloseUnneededLoops(std::stringstream &ss,
1000+ size_t &current_depth,
1001+ size_t target_depth,
1002+ std::set<int64_t> &opened_loops) {
1003+ while (current_depth > target_depth) {
1004+ current_depth--;
1005+ ss << std::string(current_depth * kIndentSpaces, ' ') << "}" << std::endl;
1006+ if (!opened_loops.empty()) {
1007+ auto it = opened_loops.end();
1008+ it--;
1009+ opened_loops.erase(it);
1010+ }
1011+ }
1012+}
1013+ 
1014+/**
1015+ * @brief 打开需要的循环
1016+ * @param ss 输出流
1017+ * @param sorted_loop_axes 排序后的 loop_axes
1018+ * @param target_depth 目标深度
1019+ * @param axis_id_to_name axis_id 到 name 的映射
1020+ * @param current_depth 当前深度(会被修改)
1021+ * @param opened_loops 已打开的循环集合(会被修改)
1022+ */
1023+static void OpenNeededLoops(std::stringstream &ss,
1024+ const std::vector<int64_t> &sorted_loop_axes,
1025+ size_t target_depth,
1026+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
1027+ size_t &current_depth,
1028+ std::set<int64_t> &opened_loops) {
1029+ for (auto axis_id: sorted_loop_axes) {
1030+ if (opened_loops.count(axis_id) == 0) {
1031+ auto depth_it = std::find(sorted_loop_axes.begin(), sorted_loop_axes.end(), axis_id);
1032+ if (depth_it != sorted_loop_axes.end()) {
1033+ size_t axis_depth = std::distance(sorted_loop_axes.begin(), depth_it) + 1;
1034+ if (axis_depth <= target_depth) {
1035+ ss << std::string(current_depth * kIndentSpaces, ' ')
1036+ << "for %" << axis_id_to_name.at(axis_id) << " in "
1037+ << axis_id_to_name.at(axis_id) << "_size {" << std::endl;
1038+ opened_loops.insert(axis_id);
1039+ current_depth++;
1040+ }
1041+ }
1042+ }
1043+ if (current_depth >= target_depth) {
1044+ break;
1045+ }
1046+ }
1047+}
1048+ 
1049+/**
1050+ * @brief 输出常规图(非子图)的循环执行内容
1051+ * @param graph 图对象
1052+ * @param axis_id_to_name axis_id 到 name 的映射
1053+ * @param axis_id_to_type axis_id 到 type 的映射
1054+ * @param vectorized_axes 向量化轴集合
1055+ * @param ssa_info SSA 映射信息
1056+ * @return 循环执行内容的字符串
1057+ */
1058+static std::string DumpRegularGraphLoopExecution(
1059+ const ascir::Graph &graph,
1060+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
1061+ const std::map<int64_t, ge::Axis::Type> &axis_id_to_type,
1062+ const std::set<int64_t> &vectorized_axes,
1063+ const SSAMappingInfo &ssa_info) {
1064+ std::stringstream ss;
1065+ 
1066+ auto all_nodes = graph.GetAllNodes();
1067+ auto sorted_loop_axes = CollectLoopAxes(graph, vectorized_axes, axis_id_to_type);
1068+ 
1069+ // 建立 loop_axis 到深度的映射
1070+ std::map<int64_t, size_t> loop_axis_to_depth;
1071+ for (size_t i = 0; i < sorted_loop_axes.size(); ++i) {
1072+ loop_axis_to_depth[sorted_loop_axes[i]] = i + 1;
1073+ }
1074+ 
1075+ bool has_loop_axis = HasLoopAxis(graph);
1076+ 
1077+ // 按拓扑序遍历节点,动态打开/关闭循环
1078+ std::set<int64_t> opened_loops;
1079+ size_t current_depth = 0;
1080+ 
1081+ for (auto node: all_nodes) {
1082+ auto node_type = node->GetType();
1083+ if (node_type == NodeType::kData || node_type == NodeType::kOutput ||
1084+ node_type == NodeType::kWorkspace) {
1085+ continue;
1086+ }
1087+ 
1088+ // 确定节点应该在哪个深度
1089+ size_t target_depth = DetermineNodeTargetDepth(node, has_loop_axis, loop_axis_to_depth,
1090+ sorted_loop_axes.size(), current_depth);
1091+ 
1092+ // 关闭不需要的循环
1093+ CloseUnneededLoops(ss, current_depth, target_depth, opened_loops);
1094+ 
1095+ // 打开需要的循环
1096+ OpenNeededLoops(ss, sorted_loop_axes, target_depth, axis_id_to_name, current_depth, opened_loops);
1097+ 
1098+ // 输出节点
1099+ DumpNodeExecution(ss, graph, node, ssa_info, axis_id_to_name, current_depth * kIndentSpaces);
1100+ }
1101+ 
1102+ // 闭合所有剩余循环
1103+ while (current_depth > 0) {
1104+ current_depth--;
1105+ ss << std::string(current_depth * kIndentSpaces, ' ') << "}" << std::endl;
1106+ }
1107+ 
1108+ return ss.str();
1109+}
1110+} // namespace
1111+ 
1112+// =============================================================================
1113+// VIEW 1: Loop Execution
1114+// =============================================================================
1115+ 
1116+std::string DumpLoopExecutionView(const ascir::Graph &graph) {
1117+ std::stringstream ss;
1118+ 
1119+ // 获取基本信息
1120+ std::string graph_name = graph.GetName();
1121+ bool is_subgraph = IsSubgraph(graph_name);
1122+ 
1123+ auto all_axis = graph.GetAllAxis();
1124+ auto axis_id_to_name = BuildAxisIdToNameMap(all_axis);
1125+ auto axis_id_to_type = BuildAxisIdToTypeMap(all_axis);
1126+ 
1127+ // 收集输入输出
1128+ std::vector<ParamInfo> inputs;
1129+ std::vector<ParamInfo> outputs;
1130+ CollectDataAndOutputNodes(graph, inputs, outputs, axis_id_to_name);
1131+ 
1132+ // 收集向量化轴
1133+ std::set<int64_t> vectorized_axes = CollectVectorizedAxes(graph);
1134+ 
1135+ // 生成说明性注释
1136+ ss << GenerateOriginalShapesComment(inputs, outputs);
1137+ 
1138+ // 生成 Tile/Block 分解注释(仅非子图)
1139+ if (!is_subgraph) {
1140+ ss << GenerateTileBlockDecompositionComment(all_axis);
1141+ }
1142+ 
1143+ // 生成函数签名
1144+ ss << GenerateFunctionSignature(graph_name, inputs, outputs);
1145+ 
1146+ // 生成函数体
1147+ if (is_subgraph) {
1148+ // 子图模式
1149+ ss << DumpSubgraphLoopExecution(graph, axis_id_to_name, axis_id_to_type);
1150+ } else {
1151+ // 非子图模式:按照 loop_axis 分层输出节点
1152+ auto all_nodes = graph.GetAllNodes();
1153+ SSAMappingInfo ssa_info = BuildSSAMapping(all_nodes);
1154+ ss << DumpRegularGraphLoopExecution(graph, axis_id_to_name, axis_id_to_type,
1155+ vectorized_axes, ssa_info);
1156+ }
1157+ 
1158+ // 返回值
1159+ if (!outputs.empty()) {
1160+ ss << " return %" << outputs[0].name << std::endl;
1161+ }
1162+ 
1163+ ss << "}" << std::endl;
1164+ 
1165+ return ss.str();
1166+}
1167+ 
1168+// =============================================================================
1169+// VIEW 2: Graph Structure 辅助函数
1170+// =============================================================================
1171+ 
1172+/**
1173+ * @brief 获取 Position 的字符串表示
1174+ */
1175+std::string PositionToString(ge::Position position) {
1176+ switch (position) {
1177+ case ge::Position::kPositionVecIn: return "VECIN";
1178+ case ge::Position::kPositionVecCalc: return "VECCALC";
1179+ case ge::Position::kPositionVecOut: return "VECOUT";
1180+ case ge::Position::kPositionGM: return "GM";
1181+ default: return "UNKNOWN";
1182+ }
1183+}
1184+ 
1185+/**
1186+ * @brief 获取 MemHardware 的字符串表示
1187+ */
1188+std::string MemHardwareToString(ge::MemHardware hardware) {
1189+ switch (hardware) {
1190+ case ge::MemHardware::kMemHardwareGM: return "GM";
1191+ case ge::MemHardware::kMemHardwareUB: return "UB";
1192+ default: return "UNKNOWN";
1193+ }
1194+}
1195+ 
1196+// =============================================================================
1197+// VIEW 2: Graph Structure
1198+// =============================================================================
1199+ 
1200+namespace {
1201+/**
1202+ * @brief 输出形状信息 (axis, repeats, strides)
1203+ */
1204+static std::stringstream &OutputShapeStr(std::stringstream &ss, const ascir::Graph &graph,
1205+ const ge::AscTensorAttr &output_attr,
1206+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
1207+ (void) graph;
1208+ // 输出 axis 列表
1209+ if (!output_attr.axis.empty()) {
1210+ ss << std::string(kPropertyIndent, ' ') << ".axis = {";
1211+ for (size_t i = 0; i < output_attr.axis.size(); ++i) {
1212+ if (i > 0) ss << ", ";
1213+ auto it = axis_id_to_name.find(output_attr.axis[i]);
1214+ ss << (it != axis_id_to_name.end() ? it->second : "unknown");
1215+ }
1216+ ss << "}" << std::endl;
1217+ }
1218+ 
1219+ // 输出 repeats
1220+ if (!output_attr.repeats.empty()) {
1221+ ss << std::string(kPropertyIndent, ' ') << ".repeats = (";
1222+ for (size_t i = 0; i < output_attr.repeats.size(); ++i) {
1223+ if (i > 0) ss << ", ";
1224+ ss << ge::SymbolicUtils::ToString(output_attr.repeats[i]);
1225+ }
1226+ ss << ")" << std::endl;
1227+ }
1228+ 
1229+ // 输出 strides
1230+ if (!output_attr.strides.empty()) {
1231+ ss << std::string(kPropertyIndent, ' ') << ".strides = (";
1232+ for (size_t i = 0; i < output_attr.strides.size(); ++i) {
1233+ if (i > 0) ss << ", ";
1234+ ss << ge::SymbolicUtils::ToString(output_attr.strides[i]);
1235+ }
1236+ ss << ")" << std::endl;
1237+ }
1238+ 
1239+ return ss;
1240+}
1241+ 
1242+/**
1243+ * @brief 输出 vectorized 信息
1244+ */
1245+static std::stringstream &OutputVectorizedStr(std::stringstream &ss, const ascir::Graph &graph,
1246+ const ge::AscTensorAttr &output_attr,
1247+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
1248+ (void) graph;
1249+ if (!output_attr.vectorized_axis.empty()) {
1250+ ss << std::string(kPropertyIndent, ' ') << ".vectorized = {";
1251+ for (size_t i = 0; i < output_attr.vectorized_axis.size(); ++i) {
1252+ if (i > 0) ss << ", ";
1253+ auto it = axis_id_to_name.find(output_attr.vectorized_axis[i]);
1254+ std::string axis_name = (it != axis_id_to_name.end()) ? it->second : "unknown";
1255+ ss << axis_name << ":";
1256+ if (i < output_attr.vectorized_strides.size()) {
1257+ ss << ge::SymbolicUtils::ToString(output_attr.vectorized_strides[i]);
1258+ }
1259+ }
1260+ ss << "}" << std::endl;
1261+ }
1262+ return ss;
1263+}
1264+ 
1265+/**
1266+ * @brief 输出内存信息
1267+ */
1268+static std::stringstream &OutputMemStr(std::stringstream &ss, const ge::AscTensorAttr &output_attr, bool verbose) {
1269+ if (!verbose && (output_attr.mem.alloc_type != ge::AllocType::kAllocTypeQueue) &&
1270+ (output_attr.mem.alloc_type != ge::AllocType::kAllocTypeBuffer)) {
1271+ return ss;
1272+ }
1273+ 
1274+ std::string pos_str = PositionToString(output_attr.mem.position);
1275+ std::string hardware_str = MemHardwareToString(output_attr.mem.hardware);
1276+ 
1277+ ss << std::string(kPropertyIndent, ' ') << ".mem = " << hardware_str << "[";
1278+ 
1279+ // 输出 tensor_id(如果存在)
1280+ if (output_attr.mem.tensor_id != ge::kIdNone) {
1281+ ss << "tensor_id=" << output_attr.mem.tensor_id << ", ";
1282+ }
1283+ 
1284+ if (output_attr.mem.alloc_type == ge::AllocType::kAllocTypeQueue) {
1285+ const auto &que = output_attr.que;
1286+ ss << "que_id=" << que.id;
1287+ if (output_attr.mem.reuse_id >= 0) {
1288+ ss << ", reuse_id=" << output_attr.mem.reuse_id;
1289+ }
1290+ ss << ", depth=" << que.depth << ", pos=" << pos_str;
1291+ } else if (output_attr.mem.alloc_type == ge::AllocType::kAllocTypeBuffer) {
1292+ ss << "buf_id=" << output_attr.buf.id;
1293+ if (output_attr.mem.reuse_id >= 0) {
1294+ ss << ", reuse_id=" << output_attr.mem.reuse_id;
1295+ }
1296+ ss << ", pos=" << pos_str;
1297+ } else {
1298+ ss << "pos=" << pos_str;
1299+ }
1300+ 
1301+ ss << "]" << std::endl;
1302+ 
1303+ return ss;
1304+}
1305+} // namespace
1306+ 
1307+// =============================================================================
1308+// VIEW 2: Graph Structure 辅助函数实现
1309+// =============================================================================
1310+ 
1311+/**
1312+ * @brief 获取 ExecuteCondition 的字符串表示
1313+ */
1314+std::string ExecuteConditionToString(ge::ExecuteCondition condition) {
1315+ switch (condition) {
1316+ case ge::ExecuteCondition::kNoCache: return "no_cache";
1317+ case ge::ExecuteCondition::kCacheBlockSplitFusedBroadcastAxis: return "cache_block_split_fused_brc_axis";
1318+ case ge::ExecuteCondition::kCacheBlockSplitOriginBroadcastAxis: return "cache_block_split_origin_brc_axis";
1319+ case ge::ExecuteCondition::kConditionInvalid: return "invalid";
1320+ default: return "unknown";
1321+ }
1322+}
1323+ 
1324+/**
1325+ * @brief 输出 Size 变量列表
1326+ */
1327+void DumpSizeVars(std::stringstream &ss, const ascir::Graph &graph) {
1328+ ss << "Sizes:" << std::endl;
1329+ auto all_size_var = graph.GetAllSizeVar();
1330+ 
1331+ for (const auto &size_var: all_size_var) {
1332+ if (size_var->expr.GetExprType() == ge::ExprType::kExprVariable) {
1333+ ss << " " << size_var->expr.Str().get() << ": VAR" << std::endl;
1334+ } else {
1335+ ss << " " << size_var->name << ": " << ge::SymbolicUtils::ToString(size_var->expr) << std::endl;
1336+ }
1337+ }
1338+}
1339+ 
1340+/**
1341+ * @brief 输出 Axis 列表
1342+ */
1343+void DumpAxisList(std::stringstream &ss, const ascir::Graph &graph,
1344+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
1345+ ss << std::endl << "Axis:" << std::endl;
1346+ auto all_axis = graph.GetAllAxis();
1347+ 
1348+ for (auto &axis: all_axis) {
1349+ ss << " " << axis->name << "(" << axis->id << ") : ";
1350+ ss << GetAxisTypeSuffix(axis->type);
1351+ ss << ", size:" << ge::SymbolicUtils::ToString(axis->size);
1352+ 
1353+ if (!axis->from.empty()) {
1354+ ss << ", from: {";
1355+ for (size_t i = 0; i < axis->from.size(); ++i) {
1356+ if (i > 0) ss << ", ";
1357+ auto it = axis_id_to_name.find(axis->from[i]);
1358+ ss << (it != axis_id_to_name.end() ? it->second : "unknown");
1359+ }
1360+ ss << "}";
1361+ }
1362+ 
1363+ ss << std::endl;
1364+ }
1365+}
1366+ 
1367+/**
1368+ * @brief 输出节点调度属性(axis, loop_axis)
1369+ */
1370+static void DumpNodeSchedProps(std::stringstream &ss,
1371+ const ge::AscNodePtr &node,
1372+ const std::map<ge::AxisId, std::string> &axis_id_to_name) {
1373+ // 输出 axis 列表
1374+ if (!node->attr.sched.axis.empty()) {
1375+ ss << std::string(kPropertyIndent, ' ') << ".axis = {";
1376+ for (size_t i = 0; i < node->attr.sched.axis.size(); ++i) {
1377+ if (i > 0) ss << ", ";
1378+ auto it = axis_id_to_name.find(node->attr.sched.axis[i]);
1379+ ss << (it != axis_id_to_name.end() ? it->second : "unknown");
1380+ }
1381+ ss << "}" << std::endl;
1382+ }
1383+ 
1384+ // 输出 loop_axis
1385+ if (node->attr.sched.loop_axis >= 0) {
1386+ auto it = axis_id_to_name.find(node->attr.sched.loop_axis);
1387+ ss << std::string(kPropertyIndent, ' ') << ".loop_axis = "
1388+ << (it != axis_id_to_name.end() ? it->second : "unknown") << std::endl;
1389+ }
1390+ 
1391+ // 输出 exec_condition(只显示非默认值)
1392+ if (node->attr.sched.exec_condition != ge::ExecuteCondition::kNoCache) {
1393+ ss << std::string(kPropertyIndent, ' ') << ".exec_condition = "
1394+ << ExecuteConditionToString(node->attr.sched.exec_condition) << std::endl;
1395+ }
1396+}
1397+ 
1398+/**
1399+ * @brief 输出节点输入
1400+ */
1401+static void DumpNodeInputs(std::stringstream &ss, const ascir::Graph &graph,
1402+ const ge::AscNodePtr &node) {
1403+ auto input_names = CollectInputNames(graph, node);
1404+ if (input_names.empty()) {
1405+ return;
1406+ }
1407+ 
1408+ // 检查是否全部为 nil
1409+ bool all_nil = true;
1410+ for (const auto &name: input_names) {
1411+ if (name != "nil") {
1412+ all_nil = false;
1413+ break;
1414+ }
1415+ }
1416+ if (all_nil) {
1417+ return;
1418+ }
1419+ 
1420+ ss << std::string(kPropertyIndent, ' ') << ".x = {";
1421+ for (size_t i = 0; i < input_names.size(); ++i) {
1422+ if (i > 0) ss << ", ";
1423+ if (input_names[i] != "nil") {
1424+ ss << input_names[i];
1425+ }
1426+ }
1427+ ss << "}" << std::endl;
1428+}
1429+ 
1430+/**
1431+ * @brief 输出节点输出
1432+ */
1433+static void DumpNodeOutputs(std::stringstream &ss, const ascir::Graph &graph,
1434+ const ge::AscNodePtr &node,
1435+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
1436+ bool verbose, bool is_subgraph) {
1437+ auto node_type = node->GetType();
1438+ // 子图模式下,只输出 Data 和 Output 节点的输出信息
1439+ if (is_subgraph && node_type != "Data" && node_type != "Output") {
1440+ return;
1441+ }
1442+ 
1443+ for (size_t i = 0; i < node->outputs().size(); ++i) {
1444+ auto &output_attr = node->outputs()[i]->attr;
1445+ 
1446+ // 输出 tensor 类型
1447+ ss << std::string(kPropertyIndent, ' ') << ".y: " << GetDtypeString(output_attr.dtype) << std::endl;
1448+ 
1449+ // 输出形状、向量化信息
1450+ OutputShapeStr(ss, graph, output_attr, axis_id_to_name);
1451+ OutputVectorizedStr(ss, graph, output_attr, axis_id_to_name);
1452+ 
1453+ // mem 信息 - 仅非子图显示
1454+ if (!is_subgraph) {
1455+ OutputMemStr(ss, output_attr, verbose);
1456+ }
1457+ }
1458+}
1459+ 
1460+/**
1461+ * @brief 输出单个节点的详细信息
1462+ */
1463+void DumpNodeDetails(std::stringstream &ss, const ascir::Graph &graph,
1464+ const ge::AscNodePtr &node, size_t idx,
1465+ const std::map<ge::AxisId, std::string> &axis_id_to_name,
1466+ bool verbose, bool is_subgraph) {
1467+ // 节点名和类型
1468+ ss << " [" << idx << "] " << node->GetName() << " : ascir.ops." << node->GetType() << std::endl;
1469+ 
1470+ // 输出调度属性
1471+ DumpNodeSchedProps(ss, node, axis_id_to_name);
1472+ 
1473+ // 输出输入
1474+ DumpNodeInputs(ss, graph, node);
1475+ 
1476+ // 输出输出
1477+ DumpNodeOutputs(ss, graph, node, axis_id_to_name, verbose, is_subgraph);
1478+}
1479+ 
1480+std::string DumpGraphStructureView(const ascir::Graph &graph, bool verbose, bool is_subgraph) {
1481+ std::stringstream ss;
1482+ 
1483+ // Header
1484+ ss << "Graph: " << graph.GetName() << std::endl;
1485+ 
1486+ // 获取轴映射
1487+ auto all_axis = graph.GetAllAxis();
1488+ auto axis_id_to_name = BuildAxisIdToNameMap(all_axis);
1489+ 
1490+ // Sizes
1491+ DumpSizeVars(ss, graph);
1492+ 
1493+ // Axis
1494+ DumpAxisList(ss, graph, axis_id_to_name);
1495+ 
1496+ // Nodes
1497+ ss << std::endl << "Nodes:" << std::endl;
1498+ auto all_nodes = graph.GetAllNodes();
1499+ size_t idx = 0UL;
1500+ 
1501+ for (auto node: all_nodes) {
1502+ DumpNodeDetails(ss, graph, node, idx++, axis_id_to_name, verbose, is_subgraph);
1503+ }
1504+ 
1505+ return ss.str();
1506+}
1507+ 
1508+namespace {
1509+/**
1510+ * @brief 收集 Queue 和 Buffer 信息
1511+ */
1512+void CollectMemoryInfo(const ascir::Graph &graph,
1513+ std::map<int32_t, dumper::QueueInfo> &queues,
1514+ std::map<int32_t, dumper::BufferInfo> &buffers) {
1515+ auto all_nodes = graph.GetAllNodes();
1516+ size_t topo_id = 0;
1517+ 
1518+ for (auto node: all_nodes) {
1519+ auto node_type = node->GetType();
1520+ if (node_type == NodeType::kData || node_type == NodeType::kOutput || node_type == NodeType::kWorkspace) {
1521+ continue;
1522+ }
1523+ 
1524+ if (!node->outputs().empty()) {
1525+ auto &output_attr = node->outputs()[0]->attr;
1526+ auto &mem = output_attr.mem;
1527+ 
1528+ if (mem.alloc_type == ge::AllocType::kAllocTypeQueue) {
1529+ int32_t que_id = output_attr.que.id;
1530+ if (queues.find(que_id) == queues.end()) {
1531+ dumper::QueueInfo info;
1532+ info.que_id = que_id;
1533+ info.depth = output_attr.que.depth;
1534+ info.position = "TPosition::" + PositionToString(mem.position);
1535+ queues[que_id] = info;
1536+ }
1537+ queues[que_id].nodes.push_back({topo_id, node->GetName(), static_cast<int32_t>(mem.reuse_id)});
1538+ } else if (mem.alloc_type == ge::AllocType::kAllocTypeBuffer) {
1539+ int32_t buf_id = output_attr.buf.id;
1540+ if (buffers.find(buf_id) == buffers.end()) {
1541+ dumper::BufferInfo info;
1542+ info.buf_id = buf_id;
1543+ buffers[buf_id] = info;
1544+ }
1545+ buffers[buf_id].nodes.push_back({topo_id, node->GetName()});
1546+ }
1547+ }
1548+ topo_id++;
1549+ }
1550+}
1551+ 
1552+/**
1553+ * @brief 输出 Queues 部分
1554+ */
1555+void DumpQueues(std::stringstream &ss, const std::map<int32_t, dumper::QueueInfo> &queues) {
1556+ ss << "# Queues (" << queues.size() << " queues)" << std::endl;
1557+ ss << std::endl;
1558+ 
1559+ for (auto &entry: queues) {
1560+ auto &info = entry.second;
1561+ ss << "Queue " << info.que_id << " [" << info.position << ", depth=" << info.depth << "]:" << std::endl;
1562+ 
1563+ // 按 reuse_id 分组
1564+ std::map<int32_t, std::vector<dumper::QueueNodeInfo> > reuse_groups;
1565+ for (auto &node_info: info.nodes) {
1566+ reuse_groups[node_info.reuse_id].push_back(node_info);
1567+ }
1568+ 
1569+ // 输出每个 reuse 组
1570+ for (auto &reuse_entry: reuse_groups) {
1571+ auto &nodes = reuse_entry.second;
1572+ ss << " ";
1573+ for (size_t i = 0; i < nodes.size(); ++i) {
1574+ if (i > 0) ss << ", ";
1575+ ss << "[" << nodes[i].topo_id << "] " << nodes[i].node_name << ".y";
1576+ }
1577+ ss << std::endl;
1578+ }
1579+ ss << std::endl;
1580+ }
1581+}
1582+ 
1583+/**
1584+ * @brief 输出 Buffers 部分
1585+ */
1586+void DumpBuffers(std::stringstream &ss, const std::map<int32_t, dumper::BufferInfo> &buffers) {
1587+ ss << "# Buffers (" << buffers.size() << " buffers)" << std::endl;
1588+ ss << std::endl;
1589+ 
1590+ for (auto &entry: buffers) {
1591+ auto &info = entry.second;
1592+ ss << "Buffer " << info.buf_id << ":" << std::endl;
1593+ 
1594+ // 按 topo_id 排序
1595+ auto sorted_nodes = info.nodes;
1596+ std::sort(sorted_nodes.begin(), sorted_nodes.end(),
1597+ [](const dumper::BufferNodeInfo &a, const dumper::BufferNodeInfo &b) {
1598+ return a.topo_id < b.topo_id;
1599+ });
1600+ 
1601+ for (auto &node_info: sorted_nodes) {
1602+ ss << " [" << node_info.topo_id << "] " << node_info.node_name << ".y" << std::endl;
1603+ }
1604+ ss << std::endl;
1605+ }
1606+}
1607+} // namespace
1608+ 
1609+std::string DumpMemoryLayoutView(const ascir::Graph &graph, bool verbose) {
1610+ if (!verbose) {
1611+ return "";
1612+ }
1613+ 
1614+ std::stringstream ss;
1615+ 
1616+ // 收集内存信息
1617+ std::map<int32_t, QueueInfo> queues;
1618+ std::map<int32_t, BufferInfo> buffers;
1619+ CollectMemoryInfo(graph, queues, buffers);
1620+ 
1621+ // 输出 Queues 和 Buffers
1622+ DumpQueues(ss, queues);
1623+ DumpBuffers(ss, buffers);
1624+ 
1625+ return ss.str();
1626+}
1627+ 
1628+std::string DumpGraphText(const ascir::Graph &graph, bool verbose, bool is_subgraph) {
1629+ std::stringstream ss;
1630+ 
1631+ // Header
1632+ ss << "================================================================================" << std::endl;
1633+ ss << "Graph: " << graph.GetName() << std::endl;
1634+ ss << "================================================================================" << std::endl;
1635+ ss << std::endl;
1636+ 
1637+ // VIEW 1: Loop Execution
1638+ ss << "--------------------------------------------------------------------------------" << std::endl;
1639+ ss << "VIEW 1: Loop Execution" << std::endl;
1640+ ss << "--------------------------------------------------------------------------------" << std::endl;
1641+ ss << DumpLoopExecutionView(graph);
1642+ ss << std::endl;
1643+ 
1644+ // VIEW 2: Graph Structure
1645+ ss << "--------------------------------------------------------------------------------" << std::endl;
1646+ ss << "VIEW 2: Graph Structure" << std::endl;
1647+ ss << "--------------------------------------------------------------------------------" << std::endl;
1648+ ss << DumpGraphStructureView(graph, verbose, is_subgraph);
1649+ ss << std::endl;
1650+ 
1651+ // VIEW 3: Memory Layout (子图不显示,非子图仅在 verbose=true 时显示)
1652+ if (!is_subgraph) {
1653+ auto memory_layout = DumpMemoryLayoutView(graph, verbose);
1654+ if (!memory_layout.empty()) {
1655+ ss << "--------------------------------------------------------------------------------" << std::endl;
1656+ ss << "VIEW 3: Memory Layout" << std::endl;
1657+ ss << "--------------------------------------------------------------------------------" << std::endl;
1658+ ss << memory_layout;
1659+ ss << std::endl;
1660+ }
1661+ }
1662+ 
1663+ ss << "================================================================================" << std::endl;
1664+ ss << "End of Dump" << std::endl;
1665+ ss << "================================================================================" << std::endl;
1666+ 
1667+ return ss.str();
1668+}
1669+} // namespace dumper
1670+} // namespace ascir
Acompiler/graph/optimize/autofuse/ascir/meta/ascendc_graph_txt_dumper.h+234-0
@@ -0,0 +1,234 @@
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+ 
11+#ifndef ASCENDC_GRAPH_TXT_DUMPER_H
12+#define ASCENDC_GRAPH_TXT_DUMPER_H
13+ 
14+#include <string>
15+#include <map>
16+#include <set>
17+#include <vector>
18+#include "ascir.h"
19+ 
20+namespace ascir {
21+namespace dumper {
22+namespace NodeType {
23+constexpr const char *kData = "Data";
24+constexpr const char *kOutput = "Output";
25+constexpr const char *kWorkspace = "Workspace";
26+constexpr const char *kScalar = "Scalar";
27+} // namespace NodeType
28+ 
29+// 魔法数字常量
30+constexpr int64_t kInvalidLoopAxis = -1;
31+constexpr int64_t kInvalidAxisId = -1;
32+constexpr size_t kIndentSpaces = 2; // 循环缩进空格数
33+constexpr size_t kPropertyIndent = 8; // 属性缩进空格数 (VIEW 2)
34+constexpr size_t kNodeIndent = 4; // 节点缩进空格数
35+ 
36+/**
37+ * @brief Dtype 信息结构体
38+ */
39+struct DtypeInfo {
40+ const char *full_name; // 完整类型名 (如 "float32")
41+ const char *short_name; // 简写类型名 (如 "f32")
42+ const char *suffix; // 后缀 (如 "32f")
43+};
44+ 
45+/**
46+ * @brief 获取 Dtype 信息
47+ * @param dtype 数据类型
48+ * @return Dtype 信息指针,如果找不到返回 nullptr
49+ */
50+const DtypeInfo *GetDtypeInfo(ge::DataType dtype);
51+ 
52+/**
53+ * @brief 获取轴类型的优先级(用于排序)
54+ * @param type 轴类型
55+ * @return 优先级值,越小越外层
56+ */
57+int32_t GetAxisTypePriority(ge::Axis::Type type);
58+ 
59+/**
60+ * @brief 获取轴类型对应的字符串后缀
61+ * @param type 轴类型
62+ * @return 类型字符串 (如 "TILE_OUT", "BLOCK_IN")
63+ */
64+std::string GetAxisTypeSuffix(ge::Axis::Type type);
65+ 
66+/**
67+ * @brief 构建 axis_id 到 axis_name 的映射
68+ * @param axes 所有轴列表
69+ * @return axis_id -> axis_name 的映射表
70+ */
71+std::map<ge::AxisId, std::string> BuildAxisIdToNameMap(const std::vector<ge::AxisPtr> &axes);
72+ 
73+/**
74+ * @brief 构建 axis_id 到 axis_type 的映射
75+ * @param axes 所有轴列表
76+ * @return axis_id -> axis_type 的映射表
77+ */
78+std::map<int64_t, ge::Axis::Type> BuildAxisIdToTypeMap(const std::vector<ge::AxisPtr> &axes);
79+ 
80+/**
81+ * @brief 从 tensor 类型字符串中提取 dtype
82+ * @param tensor_type tensor 类型字符串 (如 "f32[...]")
83+ * @return 完整的 dtype 名称 (如 "float32")
84+ */
85+std::string ExtractDtypeFromTensorType(const std::string &tensor_type);
86+ 
87+/**
88+ * @brief 从 tensor 类型字符串中提取 axis 列表
89+ * @param tensor_type tensor 类型字符串 (如 "f32[...]")
90+ * @return axis 列表部分 (如 "[...]")
91+ */
92+std::string ExtractAxisListFromTensorType(const std::string &tensor_type);
93+ 
94+/**
95+ * @brief 收集节点的输入名称列表
96+ * @param graph 图对象
97+ * @param node 节点对象
98+ * @return 输入名称列表
99+ */
100+std::vector<std::string> CollectInputNames(const ascir::Graph &graph, const ge::AscNodePtr &node);
101+ 
102+/**
103+ * @brief SSA 编号映射信息
104+ */
105+struct SSAMappingInfo {
106+ std::map<std::string, size_t> node_name_to_ssa_id; // 节点名 -> SSA 编号
107+ std::set<std::string> data_node_names; // Data 节点名称集合
108+ std::map<std::string, size_t> node_name_to_topo_id; // 节点名 -> topo_id
109+ 
110+ /**
111+ * @brief 获取节点的 SSA 编号
112+ * @param node_name 节点名称
113+ * @return SSA 编号,如果找不到返回 0
114+ */
115+ size_t GetSsaId(const std::string &node_name) const {
116+ auto it = node_name_to_ssa_id.find(node_name);
117+ return (it != node_name_to_ssa_id.end()) ? it->second : 0;
118+ }
119+ 
120+ /**
121+ * @brief 获取节点的 topo_id
122+ * @param node_name 节点名称
123+ * @return topo_id,如果找不到返回 0
124+ */
125+ size_t GetTopoId(const std::string &node_name) const {
126+ auto it = node_name_to_topo_id.find(node_name);
127+ return (it != node_name_to_topo_id.end()) ? it->second : 0;
128+ }
129+ 
130+ /**
131+ * @brief 判断是否为 Data 节点
132+ * @param node_name 节点名称
133+ * @return 如果是 Data 节点返回 true
134+ */
135+ bool IsDataNode(const std::string &node_name) const {
136+ return data_node_names.count(node_name) > 0;
137+ }
138+};
139+ 
140+/**
141+ * @brief 构建 SSA 映射信息
142+ * @param all_nodes 所有节点列表
143+ * @return SSA 映射信息
144+ */
145+SSAMappingInfo BuildSSAMapping(ge::AscNodeVisitor all_nodes);
146+ 
147+/**
148+ * @brief 参数信息(用于输入/输出)
149+ */
150+struct ParamInfo {
151+ std::string name;
152+ std::string type;
153+};
154+ 
155+/**
156+ * @brief Tile/Block 分解树的节点
157+ */
158+struct AxisTreeNode {
159+ ge::AxisPtr axis;
160+ bool is_merge;
161+ std::vector<AxisTreeNode> children;
162+};
163+ 
164+/**
165+ * @brief Queue 节点信息
166+ */
167+struct QueueNodeInfo {
168+ size_t topo_id;
169+ std::string node_name;
170+ int32_t reuse_id;
171+};
172+ 
173+/**
174+ * @brief Queue 信息
175+ */
176+struct QueueInfo {
177+ int32_t que_id;
178+ int32_t depth;
179+ std::string position;
180+ std::vector<QueueNodeInfo> nodes;
181+};
182+ 
183+/**
184+ * @brief Buffer 节点信息
185+ */
186+struct BufferNodeInfo {
187+ size_t topo_id;
188+ std::string node_name;
189+};
190+ 
191+/**
192+ * @brief Buffer 信息
193+ */
194+struct BufferInfo {
195+ int32_t buf_id;
196+ std::vector<BufferNodeInfo> nodes;
197+};
198+ 
199+/**
200+ * @brief 生成 VIEW 1: Loop Execution 的文本
201+ * @param graph 图对象
202+ * @return VIEW 1 的文本内容
203+ */
204+std::string DumpLoopExecutionView(const ascir::Graph &graph);
205+ 
206+/**
207+ * @brief 生成 VIEW 2: Graph Structure 的文本
208+ * @param graph 图对象
209+ * @param verbose 是否显示详细信息
210+ * @param is_subgraph 是否为子图
211+ * @return VIEW 2 的文本内容
212+ */
213+std::string DumpGraphStructureView(const ascir::Graph &graph, bool verbose, bool is_subgraph);
214+ 
215+/**
216+ * @brief 生成 VIEW 3: Memory Layout 的文本
217+ * @param graph 图对象
218+ * @param verbose 是否显示详细信息
219+ * @return VIEW 3 的文本内容
220+ */
221+std::string DumpMemoryLayoutView(const ascir::Graph &graph, bool verbose);
222+ 
223+/**
224+ * @brief 生成完整的图转储文本(包含三个 VIEW)
225+ * @param graph 图对象
226+ * @param verbose 是否显示详细信息
227+ * @param is_subgraph 是否为子图
228+ * @return 完整的转储文本
229+ */
230+std::string DumpGraphText(const ascir::Graph &graph, bool verbose = false, bool is_subgraph = false);
231+} // namespace dumper
232+} // namespace ascir
233+ 
234+#endif // ASCENDC_GRAPH_TXT_DUMPER_H
Mcompiler/graph/optimize/autofuse/ascir/meta/ascir_utils.cpp+38-48
@@ -13,6 +13,8 @@
13#include <fstream>13#include <fstream>
14#include <iomanip>14#include <iomanip>
15#include <queue>15#include <queue>
16+#include <set>
17+#include <algorithm>
16#include "graph/utils/type_utils.h"18#include "graph/utils/type_utils.h"
17#include "graph_utils.h"19#include "graph_utils.h"
18#include "mmpa/mmpa_api.h"20#include "mmpa/mmpa_api.h"
@@ -21,9 +23,11 @@
21#include "ascend_graph_code_dumper.h"23#include "ascend_graph_code_dumper.h"
22#include "asc_graph_dumper_context.h"24#include "asc_graph_dumper_context.h"
23#include "graph_metadef/graph/utils/file_utils.h"25#include "graph_metadef/graph/utils/file_utils.h"
26+#include "graph_metadef/graph/utils/readable_dump.h"
24#include "common_utils.h"27#include "common_utils.h"
25#include "ascir_ops_utils.h"28#include "ascir_ops_utils.h"
26#include "ascir_ops.h"29#include "ascir_ops.h"
30+#include "ascendc_graph_txt_dumper.h"
27 31 
28namespace {32namespace {
29constexpr int32_t DUMP_ID_WIDTH = 8;33constexpr int32_t DUMP_ID_WIDTH = 8;
@@ -181,18 +185,29 @@ bool CheckNeedDumpGraphBySuffix(const std::string &suffix) {
181namespace ascir::utils {185namespace ascir::utils {
182static uint64_t kDumpGraphIndex = 0UL;186static uint64_t kDumpGraphIndex = 0UL;
183static std::string DtypeToStr(ge::DataType dtype) {187static std::string DtypeToStr(ge::DataType dtype) {
184- const char *kTypeName[] = {188+ switch (dtype) {
185- [ge::DT_FLOAT] = "float32", [ge::DT_FLOAT16] = "float16", [ge::DT_INT8] = "int8_t",189+ case ge::DT_FLOAT: return "float32";
186- [ge::DT_INT32] = "int32_t", [ge::DT_UINT8] = "uint8_t", "",190+ case ge::DT_FLOAT16: return "float16";
187- [ge::DT_INT16] = "int16_t", [ge::DT_UINT16] = "uint16_t", [ge::DT_UINT32] = "uint32_t",191+ case ge::DT_INT8: return "int8_t";
188- [ge::DT_INT64] = "int64_t", [ge::DT_UINT64] = "uint64_t",192+ case ge::DT_INT32: return "int32_t";
189- };193+ case ge::DT_UINT8: return "uint8_t";
190- 194+ case ge::DT_INT16: return "int16_t";
191- if (dtype >= sizeof(kTypeName) / sizeof(kTypeName[0])) {195+ case ge::DT_UINT16: return "uint16_t";
192- return ge::TypeUtils::DataTypeToSerialString(dtype);196+ case ge::DT_UINT32: return "uint32_t";
197+ case ge::DT_INT64: return "int64_t";
198+ case ge::DT_UINT64: return "uint64_t";
199+ default: return ge::TypeUtils::DataTypeToSerialString(dtype);
193 }200 }
194- return kTypeName[dtype];201+}
195-};202+ 
203+// 构建 axis_id 到 axis_name 的映射(供 ascir_utils.cpp 内部使用)
204+static std::map<ge::AxisId, std::string> GetAxisIdToName(const std::vector<ge::AxisPtr> &axes) {
205+ std::map<ge::AxisId, std::string> axis_id_to_name;
206+ for (auto &axis : axes) {
207+ axis_id_to_name[axis->id] = axis->name;
208+ }
209+ return axis_id_to_name;
210+}
196 211 
197std::stringstream GetDumpGraphPrefixAndCreateDir() {212std::stringstream GetDumpGraphPrefixAndCreateDir() {
198 std::stringstream stream_file_name;213 std::stringstream stream_file_name;
@@ -278,14 +293,6 @@ static std::string PositionToStr(ge::Position position) {
278 return "unknown";293 return "unknown";
279}294}
280 295 
281-static std::map<ge::AxisId, std::string> GetAxisIdToName(const std::vector<ge::AxisPtr> &axes) {
282- std::map<ge::AxisId, std::string> id_to_name;
283- for (const auto &iter : axes) {
284- id_to_name[iter->id] = iter->name;
285- }
286- return id_to_name;
287-}
288- 
289static std::stringstream &GraphNameStr(std::stringstream &ss, const ascir::Graph &graph) {296static std::stringstream &GraphNameStr(std::stringstream &ss, const ascir::Graph &graph) {
290 ss << "Graph: " << graph.GetName() << std::endl;297 ss << "Graph: " << graph.GetName() << std::endl;
291 return ss;298 return ss;
@@ -401,27 +408,6 @@ static std::stringstream &NodeAttrStr(std::stringstream &ss, const ascir::Graph
401 return ss;408 return ss;
402}409}
403 410 
404-static std::vector<std::string> CollectInputNames(const ascir::Graph &graph, const ge::AscNodePtr &node) {
405- (void)graph;
406- std::vector<std::string> input_names;
407- 
408- for (uint32_t index = 0U; index < node->GetAllInDataAnchorsSize(); index++) {
409- auto in_anchor = node->GetInDataAnchor(static_cast<int32_t>(index));
410- if (in_anchor == nullptr) {
411- input_names.push_back("nil");
412- continue;
413- }
414- auto peer_out_anchor = in_anchor->GetPeerOutAnchor();
415- if (peer_out_anchor == nullptr) {
416- input_names.push_back("nil");
417- } else {
418- auto peer_name = peer_out_anchor->GetOwnerNode()->GetName();
419- input_names.push_back(peer_name + ".y");
420- }
421- }
422- return input_names;
423-}
424- 
425static std::stringstream &NodeInputStr(std::stringstream &ss, const std::vector<std::string> &input_names) {411static std::stringstream &NodeInputStr(std::stringstream &ss, const std::vector<std::string> &input_names) {
426 bool all_nil = true;412 bool all_nil = true;
427 for (const auto &name : input_names) {413 for (const auto &name : input_names) {
@@ -610,7 +596,13 @@ static void DumpGraphText(const Graph &graph, const string &suffix, const uint32
610 static std::stringstream prefix = GetDumpGraphPrefixAndCreateDir();596 static std::stringstream prefix = GetDumpGraphPrefixAndCreateDir();
611 std::stringstream ss;597 std::stringstream ss;
612 ss << prefix.str();598 ss << prefix.str();
613- auto dump_asc_graph = DebugStr(graph, verbose);599+ 
600+ // 判断是否是子图
601+ bool is_subgraph = (suffix.find("_Subgraph_") != std::string::npos);
602+ 
603+ // 使用新的 MLIR 风格格式
604+ auto dump_asc_graph = DebugStrNew(graph, verbose, is_subgraph);
605+ 
614 ss << "ascgraph_" << std::setw(DUMP_ID_WIDTH) << std::setfill('0') << kDumpGraphIndex;606 ss << "ascgraph_" << std::setw(DUMP_ID_WIDTH) << std::setfill('0') << kDumpGraphIndex;
615 ss << "_" << graph.GetName() << "_" << suffix << "_" << graph_id << ".txt";607 ss << "_" << graph.GetName() << "_" << suffix << "_" << graph_id << ".txt";
616 std::ofstream f_stream(ss.str());608 std::ofstream f_stream(ss.str());
@@ -645,9 +637,6 @@ void DumpGraph(const ascir::Graph &graph, const std::string &suffix, const uint3
645 DumpGraphText(subgraph, "_Subgraph_", graph_id, verbose);637 DumpGraphText(subgraph, "_Subgraph_", graph_id, verbose);
646 }638 }
647 639 
648- // dump onnx
649- const auto compute_graph = ge::AscGraphUtils::GetComputeGraph(graph);
650- DumpComputeGraph(compute_graph, suffix);
651 ++kDumpGraphIndex;640 ++kDumpGraphIndex;
652}641}
653 642 
@@ -660,9 +649,6 @@ void AlwaysDumpGraph(const Graph &graph, const string &suffix, const uint32_t gr
660 DumpGraphText(subgraph, "_Subgraph_", graph_id, verbose);649 DumpGraphText(subgraph, "_Subgraph_", graph_id, verbose);
661 }650 }
662 651 
663- // dump onnx
664- const auto compute_graph = ge::AscGraphUtils::GetComputeGraph(graph);
665- DumpComputeGraph(compute_graph, suffix, true);
666 ++kDumpGraphIndex;652 ++kDumpGraphIndex;
667}653}
668 654 
@@ -711,7 +697,7 @@ std::string DebugStr(const ascir::Graph &graph, bool verbose) {
711 NodeAttrStr(ss, graph, node, verbose);697 NodeAttrStr(ss, graph, node, verbose);
712 698 
713 // Node inputs699 // Node inputs
714- auto input_names = CollectInputNames(graph, node);700+ auto input_names = dumper::CollectInputNames(graph, node);
715 NodeInputStr(ss, input_names);701 NodeInputStr(ss, input_names);
716 702 
717 // Node outputs703 // Node outputs
@@ -731,6 +717,10 @@ std::string DebugImplGraphStr(const ascir::ImplGraph &graph) {
731 return DebugStr(graph, true);717 return DebugStr(graph, true);
732}718}
733 719 
720+std::string DebugStrNew(const ascir::Graph &graph, bool verbose, bool is_subgraph) {
721+ return ascir::dumper::DumpGraphText(graph, verbose, is_subgraph);
722+}
723+ 
734void DumpScheduleResult(const ascir::FusedScheduledResult &fused_scheduled_result, const std::string &suffix,724void DumpScheduleResult(const ascir::FusedScheduledResult &fused_scheduled_result, const std::string &suffix,
735 uint32_t graph_id, bool verbose) {725 uint32_t graph_id, bool verbose) {
736 for (const auto &results : fused_scheduled_result.node_idx_to_scheduled_results) {726 for (const auto &results : fused_scheduled_result.node_idx_to_scheduled_results) {
Mcompiler/graph/optimize/autofuse/ascir/meta/ascir_utils.h+5-0
@@ -44,6 +44,10 @@ std::string DebugStr(const ascir::Graph &graph, bool verbose = false);
44std::string DebugHintGraphStr(const ascir::HintGraph &graph);44std::string DebugHintGraphStr(const ascir::HintGraph &graph);
45std::string DebugImplGraphStr(const ascir::ImplGraph &graph);45std::string DebugImplGraphStr(const ascir::ImplGraph &graph);
46 46 
47+// New MLIR-style dump format
48+// is_subgraph: true for subgraph (simplified mode, VIEW3/.api.unit/.mem are not displayed)
49+std::string DebugStrNew(const ascir::Graph &graph, bool verbose = false, bool is_subgraph = false);
50+ 
47void DumpScheduleResult(const ascir::FusedScheduledResult &fused_scheduled_result, const std::string &suffix,51void DumpScheduleResult(const ascir::FusedScheduledResult &fused_scheduled_result, const std::string &suffix,
48 uint32_t graph_id = 0U, bool verbose = true);52 uint32_t graph_id = 0U, bool verbose = true);
49 53 
@@ -56,6 +60,7 @@ bool IsConcatAllInputsAligned(const ge::AscNode &node);
56ge::TriBool AreConcatInputShapesEqual(const ge::AscNodePtr &node);60ge::TriBool AreConcatInputShapesEqual(const ge::AscNodePtr &node);
57 61 
58bool AreAllInputsLoad(const ge::NodePtr &node);62bool AreAllInputsLoad(const ge::NodePtr &node);
63+ 
59} // namespace ascir::utils64} // namespace ascir::utils
60 65 
61#endif66#endif
Mcompiler/graph/optimize/autofuse/autofuse/can_fuse/backend/backend_utils.cpp+5-0
@@ -199,6 +199,11 @@ bool IsSplitComplete(const NodePtr &node) {
199 if (ascir_node->GetType() == kSplitType) {199 if (ascir_node->GetType() == kSplitType) {
200 fused_split_num++;200 fused_split_num++;
201 }201 }
202+ if (kPureSplitIncludedAscirNodeTypes.count(ascir_node->GetType()) == 0U) {
203+ GELOGD("split AscBackend node %s has ascir node %s(%s), has fused with other types of AscBackend",
204+ node->GetName().c_str(), ascir_node->GetType().c_str(), ascir_node->GetName().c_str());
205+ return false;
206+ }
202 }207 }
203 GELOGD("split node %s, original node %s, original output num %zu, fused split node %zu", node->GetName().c_str(),208 GELOGD("split node %s, original node %s, original output num %zu, fused split node %zu", node->GetName().c_str(),
204 origin_node->GetName().c_str(), origin_output_num, fused_split_num);209 origin_node->GetName().c_str(), origin_output_num, fused_split_num);
Mcompiler/graph/optimize/autofuse/autofuse/can_fuse/backend/backend_utils.h+1-0
@@ -41,6 +41,7 @@ const std::string kSqueezeType = "Squeeze";
41const std::string kUnsqueezeType = "Unsqueeze";41const std::string kUnsqueezeType = "Unsqueeze";
42const ge::Expression kSymbolZero = ge::Symbol(0);42const ge::Expression kSymbolZero = ge::Symbol(0);
43const ge::Expression kSymbolOne = ge::Symbol(1);43const ge::Expression kSymbolOne = ge::Symbol(1);
44+const std::set kPureSplitIncludedAscirNodeTypes({kSplitType, kDataType, kLoadType, kStoreType, kOutputType});
44 45 
45struct NodeFuseInfo;46struct NodeFuseInfo;
46struct ComparePairs;47struct ComparePairs;
Mcompiler/graph/optimize/autofuse/autofuse/can_fuse/strategy/split_fusion_strategy.cpp+1-1
@@ -63,7 +63,7 @@ bool SplitFusionStrategy::CanFuse(const NodePtr &node1, const NodePtr &node2) {
63 return false;63 return false;
64 }64 }
65 // split不做水平融合65 // split不做水平融合
66- if (BackendUtils::IsHorizontal(node1, node2)) {66+ if (!BackendUtils::IsVertical(node1, node2)) {
67 GELOGI("node1 %s(%s) and node2 %s(%s) can not fuse, the reason is [%s][split cannot fuse other node horizontal.]",67 GELOGI("node1 %s(%s) and node2 %s(%s) can not fuse, the reason is [%s][split cannot fuse other node horizontal.]",
68 node1->GetName().c_str(), node1->GetType().c_str(), node2->GetName().c_str(), node2->GetType().c_str(),68 node1->GetName().c_str(), node1->GetType().c_str(), node2->GetName().c_str(), node2->GetType().c_str(),
69 ge::NotFuseReasonCode(ge::NotFuseReason::kSplitCanNotFuseHorizontal));69 ge::NotFuseReasonCode(ge::NotFuseReason::kSplitCanNotFuseHorizontal));
Mcompiler/graph/optimize/autofuse/autofuse/lowering/op_lowering_impl/lowering_impl.cpp+2-2
@@ -491,13 +491,13 @@ graphStatus ParseSplitNodeAndValidate(const NodePtr &split_node, InDataAnchorPtr
491 491 
492graphStatus ComputeSplitSplits(const NodePtr &node, const Expression &x_dim, vector<Expression> &size_splits) {492graphStatus ComputeSplitSplits(const NodePtr &node, const Expression &x_dim, vector<Expression> &size_splits) {
493 vector<int64_t> num_split_list = {};493 vector<int64_t> num_split_list = {};
494- GE_ASSERT_GRAPH_SUCCESS(AutofuseUtils::GetListIntByInputOrAttr(node, num_split_list, "num_split", "num_split"),494+ GE_WARN_ASSERT(AutofuseUtils::GetListIntByInputOrAttr(node, num_split_list, "num_split", "num_split"),
495 "Skip lowering node %s, as: Failed to get num_split.", node->GetNamePtr());495 "Skip lowering node %s, as: Failed to get num_split.", node->GetNamePtr());
496 GE_ASSERT(!num_split_list.empty());496 GE_ASSERT(!num_split_list.empty());
497 497 
498 vector<int64_t> size_splits_list = {};498 vector<int64_t> size_splits_list = {};
499 if (node->GetType() == AF_SPLITVD || node->GetType() == AF_SPLITV) {499 if (node->GetType() == AF_SPLITVD || node->GetType() == AF_SPLITV) {
500- GE_ASSERT_GRAPH_SUCCESS(AutofuseUtils::GetListIntByInputOrAttr(node, size_splits_list, "size_splits", "size_splits"),500+ GE_WARN_ASSERT(AutofuseUtils::GetListIntByInputOrAttr(node, size_splits_list, "size_splits", "size_splits"),
501 "Skip lowering node %s, as: Failed to get size_splits .", node->GetNamePtr());501 "Skip lowering node %s, as: Failed to get size_splits .", node->GetNamePtr());
502 GE_ASSERT(!size_splits_list.empty());502 GE_ASSERT(!size_splits_list.empty());
503 for (size_t i = 0U; i < size_splits_list.size(); ++i) {503 for (size_t i = 0U; i < size_splits_list.size(); ++i) {
Mdocs/es/README.md+3-3
@@ -81,8 +81,8 @@ docs/es/
81### API 集成81### API 集成
82 82 
83- [x] [***December 2025***]math 分包已完成ES API集成。83- [x] [***December 2025***]math 分包已完成ES API集成。
84-- [ ] [***February 2026***]nn、cv、transformer、hcom分包完成ES API集成。84+- [x] [***February 2026***]nn、cv、transformer完成ES API集成。
85-- [ ] [***March 2026***]hcom分包完成ES API集成。85+- [ ] [***April 2026***]hcom分包完成ES API集成。
86 86 
87注:在全量原型的ES API打包到各个算子分包之前,如需使用 ES API,可以参考工具文档中的 [generate_es_package.cmake](tools/generate_es_package_cmake_readme.md) 进行代码生成和集成。87注:在全量原型的ES API打包到各个算子分包之前,如需使用 ES API,可以参考工具文档中的 [generate_es_package.cmake](tools/generate_es_package_cmake_readme.md) 进行代码生成和集成。
88 88 
@@ -95,7 +95,7 @@ docs/es/
95### 后向兼容95### 后向兼容
96- [x] [***December 2025***]Python API后向兼容完成设计并落地。96- [x] [***December 2025***]Python API后向兼容完成设计并落地。
97- [x] [***January 2026***]C++ API后向兼容性设计完成;C++ API的后向兼容依赖完成`历史原型库`的设计方案。97- [x] [***January 2026***]C++ API后向兼容性设计完成;C++ API的后向兼容依赖完成`历史原型库`的设计方案。
98-- [ ] [***March 2026***]C++ API后向兼容性代码开发完成;实现C++构图场景的完整向后兼容能力。98+- [x] [***March 2026***]C++ API后向兼容性代码开发完成;实现C++构图场景的完整向后兼容能力。
99 99 
100### 自定义算子工程集成100### 自定义算子工程集成
101 101 
Mdocs/es/tools/generate_es_package_cmake_readme.md+110-6
@@ -74,6 +74,8 @@ make my_app
74 74 
75## 参数说明75## 参数说明
76 76 
77+### 函数参数
78+ 
77两个函数参数完全相同:79两个函数参数完全相同:
78 80 
79| 参数 | 必需性 | 说明 | 示例 |81| 参数 | 必需性 | 说明 | 示例 |
@@ -92,6 +94,21 @@ make my_app
92 类型的 `ES_LINKABLE_AND_ALL_TARGET` 的原因94 类型的 `ES_LINKABLE_AND_ALL_TARGET` 的原因
93- 函数会自动从 `OPP_PROTO_TARGET``LIBRARY_OUTPUT_DIRECTORY` 推导原型库路径,这是生成原型库对应的 ES 产物的基本条件95- 函数会自动从 `OPP_PROTO_TARGET``LIBRARY_OUTPUT_DIRECTORY` 推导原型库路径,这是生成原型库对应的 ES 产物的基本条件
94 96 
97+### 历史原型库相关 CMake 变量
98+ 
99+以下变量在调用函数前通过 `set()` 设置,用于控制历史原型库功能:
100+ 
101+| 变量 | 类型 | 说明 | 示例 |
102+|------|------|------|------|
103+| `GE_ES_EXTRACT_HISTORY` | bool(可选) | ON 时向 gen_esb 传入 `--es_mode=extract_history`,启用**历史原型库生成模式**(归档当前原型为 JSON,供后续版本代码生成时使用);不设置或 OFF 则 gen_esb 默认 `codegen`(仅生成 C++ API) | `set(GE_ES_EXTRACT_HISTORY ON)` |
104+| `GE_ES_RELEASE_VERSION` | 可选 | **当前新版本号**,归档步骤将当前原型归档为此版本;历史原型库生成模式下必须设置 | `set(GE_ES_RELEASE_VERSION "8.0.RC1")` |
105+| `GE_ES_RELEASE_DATE` | 可选 | 历史原型库生成模式下指定发布日期(格式 `YYYY-MM-DD`),不设置则由 gen_esb 使用当前日期 | `set(GE_ES_RELEASE_DATE "2026-02-28")` |
106+| `GE_ES_BRANCH_NAME` | 可选 | 历史原型库生成模式下指定发布分支名。**注意**:当设为 `master` 时,函数会忽略所有归档相关变量(`GE_ES_EXTRACT_HISTORY`/`GE_ES_RELEASE_VERSION`/`GE_ES_RELEASE_DATE`),仅走纯代码生成模式 | `set(GE_ES_BRANCH_NAME "release/8.0")` |
107+ 
108+> **历史原型库路径自动推导**:函数内部根据 cmake 文件安装位置自动推导 `${CANN_INSTALL_PATH}/cann/opp/history_registry/<module>` 路径,路径存在且非空时自动向 gen_esb 传入 `--history_registry`,**调用方无需显式设置历史原型库路径**
109+>
110+> **完整商发模式**:`GE_ES_EXTRACT_HISTORY=ON` 且 ops 包中存在历史原型库时,`add_es_library` 内部自动串行执行两次 gen_esb(代码生成 + 历史原型库归档&合并),**调用方无需额外处理**,一次 `add_es_library` 调用即可完成完整商发所需的全部操作(参见示例 9)。
111+ 
95## 输出产物112## 输出产物
96 113 
97### add_es_library_and_whl 生成的产物114### add_es_library_and_whl 生成的产物
@@ -104,7 +121,8 @@ OUTPUT_PATH/
104│ ├── es_math_ops_c.h # C 接口聚合头文件121│ ├── es_math_ops_c.h # C 接口聚合头文件
105│ └── es_add.h ... # 单个算子头文件(一般是有多个文件)122│ └── es_add.h ... # 单个算子头文件(一般是有多个文件)
106├── lib64/123├── lib64/
107-── libes_math.so # 动态库124+── libes_math.so # 动态库
125+│ └── libes_math.a # 静态库
108└── whl/126└── whl/
109 └── es_math-1.0.0-py3-none-any.whl # Python 包127 └── es_math-1.0.0-py3-none-any.whl # Python 包
110```128```
@@ -119,9 +137,32 @@ OUTPUT_PATH/
119│ ├── es_math_ops_c.h # C 接口聚合头文件137│ ├── es_math_ops_c.h # C 接口聚合头文件
120│ └── es_add.h ... # 单个算子头文件(一般是有多个文件)138│ └── es_add.h ... # 单个算子头文件(一般是有多个文件)
121└── lib64/139└── lib64/
122- ── libes_math.so # 动态库140+ ── libes_math.so # 动态库
141+ └── libes_math.a # 静态库
123```142```
124-**聚合的含义**:包含 es_math 下所有算子的构图 API143+ 
144+**说明**
145+- **聚合的含义**:包含 es_math 下所有算子的构图 API
146+- **动态库与静态库**:每次生成会同时产出 `lib<name>.so``lib<name>.a`。对外接口 target(如 `es_math`)默认链接动态库;若需静态链接,可手动指定 `lib64/lib<name>.a` 或通过 `target_link_libraries(your_target PRIVATE ${OUTPUT_PATH}/lib64/libes_math.a)` 等方式链接静态库。
147+ 
148+### 启用历史原型库相关模式后的额外产物
149+ 
150+#### 历史原型库生成模式(`GE_ES_EXTRACT_HISTORY=ON`)
151+ 
152+gen_esb 直接输出到 `OUTPUT_PATH`,生成以下 JSON 结构:
153+ 
154+```
155+OUTPUT_PATH/
156+├── index.json # 版本索引(所有已归档版本的列表)
157+└── registry/
158+ └── <GE_ES_RELEASE_VERSION>/
159+ ├── metadata.json # 版本元信息(版本号、发布日期、分支名等)
160+ └── operators.json # 算子原型数据(IR 结构化描述)
161+```
162+ 
163+#### 代码生成模式含历史兼容(自动检测到历史原型库时)
164+ 
165+C++ 头文件中同一算子会出现多版本重载签名(历史版本签名 + 当前版本签名),`.so` 同时包含所有版本的实现,向前兼容旧版本调用方式。产物目录结构与标准模式相同,仅头文件内容有差异。
125 166 
126## 生成的 Target167## 生成的 Target
127 168 
@@ -129,7 +170,7 @@ OUTPUT_PATH/
129 170 
130| Target 名称 | 用途 | 说明 |171| Target 名称 | 用途 | 说明 |
131|------------|------|------|172|------------|------|------|
132-| `es_math` | **链接依赖** | **使用方通过此 target 链接,自动触发构建** |173+| `es_math` | **链接依赖** | **使用方通过此 target 链接,自动触发构建**;默认链接动态库(.so),静态库(.a)同时生成在 `lib64/` 下,需静态链接时请直接指定静态库文件。 |
133 174 
134## 使用示例175## 使用示例
135 176 
@@ -267,6 +308,57 @@ graph = builder.build_and_reset()
267- 可以使用 `ge.es.list_plugins()` 查看所有已加载的插件名称308- 可以使用 `ge.es.list_plugins()` 查看所有已加载的插件名称
268- 可以使用 `ge.es.get_plugin('math')` 检查插件是否存在(返回模块对象或 None)。309- 可以使用 `ge.es.get_plugin('math')` 检查插件是否存在(返回模块对象或 None)。
269 310 
311+### 示例 7:历史原型库生成模式(商发首次构建,归档当前版本原型)
312+ 
313+```cmake
314+# 从已安装的算子原型 .so 中提取 IR 原型,归档为 JSON 供下次商发使用
315+set(GE_ES_EXTRACT_HISTORY ON)
316+set(GE_ES_RELEASE_VERSION "8.0.RC1")
317+set(GE_ES_RELEASE_DATE "2026-02-28") # 可选,不设置则使用当前日期
318+set(GE_ES_BRANCH_NAME "release/8.0") # 可选;若设为 master 则不会执行归档,仅走代码生成
319+ 
320+add_es_library(
321+ ES_LINKABLE_AND_ALL_TARGET es_math
322+ OPP_PROTO_TARGET opgraph_math
323+ OUTPUT_PATH ${CMAKE_BINARY_DIR}/output
324+)
325+# 产物:output/index.json, output/registry/8.0.RC1/metadata.json, output/registry/8.0.RC1/operators.json
326+```
327+ 
328+### 示例 8:代码生成模式含历史兼容(自动消费已有历史数据,生成带重载的 C++ API)
329+ 
330+```cmake
331+# 函数内部自动检测 ${CANN_INSTALL_PATH}/cann/opp/history_registry/math,
332+# 路径存在且非空时自动生成带历史兼容重载签名的 C++ 接口,无需手动设置路径
333+set(GE_ES_RELEASE_VERSION "8.0.RC2")
334+ 
335+add_es_library(
336+ ES_LINKABLE_AND_ALL_TARGET es_math
337+ OPP_PROTO_TARGET opgraph_math
338+ OUTPUT_PATH ${CMAKE_BINARY_DIR}/output
339+)
340+# 产物头文件中同一算子出现多版本重载(旧签名 + 新签名),向前兼容旧版本调用
341+```
342+ 
343+### 示例 9:完整商发模式(单次调用,函数内部自动完成代码生成 + 历史原型库归档&合并)
344+ 
345+```cmake
346+# GE_ES_EXTRACT_HISTORY=ON + ops 包中存在历史原型库(自动检测)= 完整商发模式
347+# add_es_library 内部自动串行执行两次 gen_esb,调用方无需额外处理:
348+# gen_esb 调用1:默认 codegen 模式,以当前日期为锚点自动选取窗口内历史版本 → 对比当前原型 → 生成带重载 C++ API
349+# gen_esb 调用2:--es_mode=extract_history,将已有历史库从 _AUTO_HISTORY_REGISTRY 复制至 OUTPUT_PATH,在 OUTPUT_PATH 追加当前版本原型 → OUTPUT_PATH 包含完整历史原型库
350+set(GE_ES_EXTRACT_HISTORY ON)
351+set(GE_ES_RELEASE_VERSION "8.0.RC2") # 当前新版本号,用于归档步骤
352+set(GE_ES_RELEASE_DATE "2026-02-28") # 可选
353+set(GE_ES_BRANCH_NAME "develop") # 可选;若设为 master 则不会归档,仅走代码生成
354+ 
355+add_es_library(
356+ ES_LINKABLE_AND_ALL_TARGET es_math
357+ OPP_PROTO_TARGET opgraph_math
358+ OUTPUT_PATH ${CMAKE_BINARY_DIR}/output
359+)
360+```
361+ 
270## 命名规则362## 命名规则
271 363 
272### 产物命名364### 产物命名
@@ -274,6 +366,7 @@ graph = builder.build_and_reset()
274| 产物类型 | 命名规则 | 示例 (ES_LINKABLE_AND_ALL_TARGET=es_math) |366| 产物类型 | 命名规则 | 示例 (ES_LINKABLE_AND_ALL_TARGET=es_math) |
275|---------|---------|--------------------------------|367|---------|---------|--------------------------------|
276| 动态库 | `lib<ES_LINKABLE_AND_ALL_TARGET>.so` | `libes_math.so` |368| 动态库 | `lib<ES_LINKABLE_AND_ALL_TARGET>.so` | `libes_math.so` |
369+| 静态库 | `lib<ES_LINKABLE_AND_ALL_TARGET>.a` | `libes_math.a` |
277| Python 包 | `<ES_LINKABLE_AND_ALL_TARGET>-1.0.0-py3-none-any.whl` | `es_math-1.0.0-py3-none-any.whl` |370| Python 包 | `<ES_LINKABLE_AND_ALL_TARGET>-1.0.0-py3-none-any.whl` | `es_math-1.0.0-py3-none-any.whl` |
278| 聚合头文件 | `es_<name>_ops.h` | `es_math_ops.h` |371| 聚合头文件 | `es_<name>_ops.h` | `es_math_ops.h` |
279 372 
@@ -291,6 +384,17 @@ graph = builder.build_and_reset()
291 - 使用小写字母和下划线384 - 使用小写字母和下划线
292 - 避免使用特殊字符和 C++ 关键字385 - 避免使用特殊字符和 C++ 关键字
293 386 
387+2. **历史原型库相关变量**
388+ - 历史原型库路径由函数**自动推导**`${CANN_INSTALL_PATH}/cann/opp/history_registry/<module>`),路径存在且非空时自动启用,调用方无需传参
389+ - **master 分支**:当 `GE_ES_BRANCH_NAME``master` 时,会忽略 `GE_ES_EXTRACT_HISTORY`/`GE_ES_RELEASE_VERSION`/`GE_ES_RELEASE_DATE`,仅走纯代码生成模式(历史原型库路径仍会传递,用于生成带重载的 C++ API)
390+ - `GE_ES_EXTRACT_HISTORY=ON` 且 ops 包中存在历史原型库(自动检测到)即为**完整商发模式**,函数内部自动执行两次 gen_esb(代码生成 + 历史原型库归档&合并),调用方无需任何额外处理(参见示例 9)
391+ - **版本去重**:若历史原型库的 `index.json` 中已存在与 `GE_ES_RELEASE_VERSION` 相同的版本号,则跳过归档步骤,仅执行代码生成(避免重复归档);同时将 CANN 安装路径中的历史原型库完整复制到 `OUTPUT_PATH`,方便后续换路径安装
392+ - 纯历史归档模式(仅设置 `GE_ES_EXTRACT_HISTORY=ON`,ops 包中无历史原型库):gen_esb 输出到 `OUTPUT_PATH`,只生成 JSON,不生成 C++ API
393+ - 完整商发模式下,代码生成步骤 gen_esb 不传 `--release_version`,以当前日期为锚点自动选取窗口内历史版本对比;归档步骤使用 `GE_ES_RELEASE_VERSION` 作为新版本号写入历史库
394+ - 完整商发模式下,归档步骤将已有历史库从 `_AUTO_HISTORY_REGISTRY`(CANN 安装路径,只读)复制到 `OUTPUT_PATH`(构建目录,可写),gen_esb 在 `OUTPUT_PATH` 追加当前版本条目;首次构建(CANN 路径中无已有历史库)时直接输出至 `OUTPUT_PATH`;最终 `OUTPUT_PATH` 包含所有历史版本 + 当前版本的完整合并结果
395+ - `GE_ES_RELEASE_VERSION` 归档时必须设置,否则归档版本无法识别
396+ - 历史原型库数据(JSON 文件)通常随 ops 包安装,默认位于 `${CANN_INSTALL_PATH}/cann/opp/history_registry/<package_name>/`
397+ 
294 398 
295## 依赖要求399## 依赖要求
296 400 
@@ -327,8 +431,8 @@ add_es_library_and_whl(
327# │ ├── es_math/431# │ ├── es_math/
328# │ └── es_nn/432# │ └── es_nn/
329# ├── lib64/433# ├── lib64/
330-# │ ├── libes_math.so434+# │ ├── libes_math.so, libes_math.a
331-# │ └── libes_nn.so435+# │ └── libes_nn.so, libes_nn.a
332# └── whl/436# └── whl/
333# ├── es_math-1.0.0-py3-none-any.whl437# ├── es_math-1.0.0-py3-none-any.whl
334# └── es_nn-1.0.0-py3-none-any.whl438# └── es_nn-1.0.0-py3-none-any.whl
Mdocs/ge_python/README.md+2-1
@@ -57,7 +57,8 @@ GE-PY 模块包含以下核心组件:
57### API 集成57### API 集成
58 58 
59- [x] [***December 2025***]基础接口已经完成设计和落地。59- [x] [***December 2025***]基础接口已经完成设计和落地。
60-- [ ] [***February 2026***] es 的 python 算子 api 支持,详见[es api集成路标](../es/README.md#api-集成)。60+- [x] [***February 2026***] es 的 python 算子 api 支持,详见[es api集成路标](../es/README.md#api-集成)。
61+- [ ] [***March 2026***] 图异步执行的python接口提供
61 62 
62### sample和相关文档63### sample和相关文档
63 64 
Mexamples/acl/1_sample_resnet50_imagenet_classification/README.md+18-13
@@ -33,9 +33,12 @@
33├── CMakeLists.txt //编译脚本,调用src目录下的CMakeLists文件33├── CMakeLists.txt //编译脚本,调用src目录下的CMakeLists文件
34```34```
35 35 
36-## 环境要求36+## 环境准备
37- 37+- 通过安装指导 [环境准备](../../../docs/build.md#2-安装软件包)正确安装`toolkit`和`ops`包
38-- 已完成[昇腾AI软件栈在开发环境上的部署](https://www.hiascend.com/document/redirect/CannCommunityInstSoftware)38+- 设置环境变量 (假设包安装在/usr/local/Ascend/)
39+```
40+source /usr/local/Ascend/cann/set_env.sh
41+```
39 42 
40## 实现步骤43## 实现步骤
41 44 
@@ -43,7 +46,7 @@
43 46 
442. 下载代码并上传至环境后,请先进入根目录下"examples/acl/1_sample_resnet50_imagenet_classification"样例目录。472. 下载代码并上传至环境后,请先进入根目录下"examples/acl/1_sample_resnet50_imagenet_classification"样例目录。
45 48 
46- 请注意,下文中的样例目录均指examples/acl/1_sample_resnet50_imagenet_classification目录。49+ 请注意,下文中的样例目录均指"examples/acl/1_sample_resnet50_imagenet_classification"目录。
47 50 
483. 准备ResNet-50模型。513. 准备ResNet-50模型。
49 1. 获取ResNet-50原始模型。52 1. 获取ResNet-50原始模型。
@@ -57,6 +60,7 @@
57 切换到样例目录,执行如下命令(以Atlas A2系列产品为例):60 切换到样例目录,执行如下命令(以Atlas A2系列产品为例):
58 61 
59 ```62 ```
63+ cd "样例目录/model"
60 atc --model=resnet50_Opset16.onnx --framework=5 --output=resnet50 --soc_version=Ascend910B1 --input_format=NCHW --output_type=FP3264 atc --model=resnet50_Opset16.onnx --framework=5 --output=resnet50 --soc_version=Ascend910B1 --input_format=NCHW --output_type=FP32
61 ```65 ```
62 66 
@@ -64,26 +68,27 @@
64 - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。68 - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。
65 - --soc\_version:昇腾AI处理器的版本。版本获取可参考[Link](https://hiascend.com/document/redirect/CannCommunityAtcSocVersion)。69 - --soc\_version:昇腾AI处理器的版本。版本获取可参考[Link](https://hiascend.com/document/redirect/CannCommunityAtcSocVersion)。
66 - --output\_type:指定输出的数据类型为float32。70 - --output\_type:指定输出的数据类型为float32。
67- - --output:生成的resnet50.om文件存放在样例目录/model目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_resnet50\_imagenet\_classification.cpp 中的omModelPath参数值。71+ - --output:生成的resnet50.om文件存放在"样例目录/model"目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_resnet50\_imagenet\_classification.cpp 中的omModelPath参数值。
68 72 
69 ```73 ```
70 const char* omModelPath = "../model/resnet50.om";74 const char* omModelPath = "../model/resnet50.om";
71 ```75 ```
72 76 
734. 准备测试图片。774. 准备测试图片。
74- 1. 请从以下链接获取样例的输入图片,并以运行用户将获取的文件上传至开发环境的"样例目录/data"目录下。如果目录不存在,需自行创建。78+ 1. 按照以命令获取样例的输入图片,输入图片需要放置到"样例目录/data"目录下。如果目录不存在,需自行创建。如果wget失败,您也可以直接在浏览器中输入以下链接下载后上传至"样例目录/data"目录。
79+ ```
80+ cd "样例目录/data"
81+ wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg
82+ wget https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg
83+ ```
75 84 
76- [https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1\_1024\_683.jpg](https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog1_1024_683.jpg)85+ 2. 切换到"样例目录/data"目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在"样例目录/data"目录下生成2个\*.bin文件。
77- 
78- [https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog2\_1024\_683.jpg](https://obs-9be7.obs.cn-east-2.myhuaweicloud.com/models/aclsample/dog2_1024_683.jpg)
79- 
80- 2. 切换到“样例目录/data“目录下,执行transferPic.py脚本,将\*.jpg转换为\*.bin,同时将图片从1024\*683的分辨率缩放为224\*224。在“样例目录/data“目录下生成2个\*.bin文件。
81 86 
82 ```87 ```
83 python3 ../scripts/transferPic.py88 python3 ../scripts/transferPic.py
84 ```89 ```
85 90 
86- 如果执行脚本报错ModuleNotFoundError: No module named 'PIL',则表示缺少Pillow库,请使用**pip3 install Pillow --user**命令安装Pillow库。91+ 如果执行脚本报错"ModuleNotFoundError: No module named 'PIL'",则表示缺少Pillow库,请使用**pip3 install Pillow --user**命令安装Pillow库。
87 92 
88## 构建验证93## 构建验证
89 94 
@@ -97,7 +102,7 @@
97 102 
98 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。103 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。
99 104 
100- **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找Ascend-cann-toolkit安装目录/lib64目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。105+ **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找"Ascend-cann-toolkit安装目录/lib64"目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。
101 106 
102 - 配置示例如下所示:107 - 配置示例如下所示:
103 108 
Mexamples/acl/2_sample_resnet50_imagenet_classification_dynmaic_batch/README.md+11-7
@@ -2,7 +2,7 @@
2 2 
3## 功能描述3## 功能描述
4 4 
5-该样例主要是基于Onnx ResNet-50网络(单输入、动态多Batch)实现图片分类的功能。5+该样例主要是基于Onnx ResNet-50网络(单输入、Batch)实现多batch场景下图片分类的功能。
6 6 
7在该样例中:7在该样例中:
81. 先使用样例提供的脚本transferPic.py,将2张\*.jpg图片都转换为\*.bin格式,同时将图片从1024\*683的分辨率缩放为224\*224。81. 先使用样例提供的脚本transferPic.py,将2张\*.jpg图片都转换为\*.bin格式,同时将图片从1024\*683的分辨率缩放为224\*224。
@@ -35,7 +35,11 @@
35 35 
36## 环境要求36## 环境要求
37 37 
38-- 已完成[昇腾AI软件栈在开发环境上的部署](https://www.hiascend.com/document/redirect/CannCommunityInstSoftware)38+- 通过安装指导 [环境准备](https://gitcode.com/cann/ge/blob/master/docs/build.md#2-%E5%AE%89%E8%A3%85%E8%BD%AF%E4%BB%B6%E5%8C%85) 正确安装 `toolkit` 和 `ops` 包
39+- 设置环境变量(假设包安装在/usr/local/Ascend/)
40+ ```
41+ source /usr/local/Ascend/cann/set_env.sh
42+ ```
39 43 
40## 实现步骤44## 实现步骤
41 45 
@@ -43,7 +47,7 @@
43 47 
442. 下载代码并上传至环境后,请先进入根目录下"examples/acl/2_sample_resnet50_imagenet_classification_dynamic_batch"样例目录。482. 下载代码并上传至环境后,请先进入根目录下"examples/acl/2_sample_resnet50_imagenet_classification_dynamic_batch"样例目录。
45 49 
46- 请注意,下文中的样例目录均指examples/acl/2_sample_resnet50_imagenet_classification_dynamic_batch目录。50+ 请注意,下文中的样例目录均指"examples/acl/2_sample_resnet50_imagenet_classification_dynamic_batch"目录。
47 51 
483. 准备ResNet-50模型。523. 准备ResNet-50模型。
49 1. 获取ResNet-50原始模型。53 1. 获取ResNet-50原始模型。
@@ -63,10 +67,10 @@
63 - --model:原始模型文件路径。67 - --model:原始模型文件路径。
64 - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。68 - --framework:原始框架类型。0:表示Caffe;1:表示MindSpore;3:表示TensorFlow;5:表示ONNX。
65 - --soc\_version:昇腾AI处理器的版本。版本获取可参考[Link](https://hiascend.com/document/redirect/CannCommunityAtcSocVersion)。69 - --soc\_version:昇腾AI处理器的版本。版本获取可参考[Link](https://hiascend.com/document/redirect/CannCommunityAtcSocVersion)。
66- - --output\_type:指定输出的数据类型为float32。
67- - --output:生成的resnet50.om文件存放在“样例目录/model“目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_resnet50\_imagenet\_classification.cpp 中的omModelPath参数值。
68 - --input\_shape: 指定输入数据的shape值,其中不想指定的维度可以将其设置为-1。70 - --input\_shape: 指定输入数据的shape值,其中不想指定的维度可以将其设置为-1。
69 - --dynamic\_batch\_size: 设置动态batch_size参数。71 - --dynamic\_batch\_size: 设置动态batch_size参数。
72+ - --output\_type:指定输出的数据类型为float32。
73+ - --output:生成的resnet50.om文件存放在“样例目录/model“目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_resnet50\_imagenet\_classification.cpp 中的omModelPath参数值。
70 74 
71 ```75 ```
72 const char* omModelPath = "../model/resnet50_dynamic_batch.om";76 const char* omModelPath = "../model/resnet50_dynamic_batch.om";
@@ -85,7 +89,7 @@
85 python3 ../scripts/transferPic.py89 python3 ../scripts/transferPic.py
86 ```90 ```
87 91 
88- 如果执行脚本报错ModuleNotFoundError: No module named 'PIL',则表示缺少Pillow库,请使用**pip3 install Pillow --user**命令安装Pillow库。92+ 如果执行脚本报错"ModuleNotFoundError: No module named 'PIL'",则表示缺少Pillow库,请使用**pip3 install Pillow --user**命令安装Pillow库。
89 93 
90## 构建验证94## 构建验证
91 95 
@@ -99,7 +103,7 @@
99 103 
100 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。104 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。
101 105 
102- **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找Ascend-cann-toolkit安装目录/lib64目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。106+ **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找"Ascend-cann-toolkit安装目录/lib64"目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。
103 107 
104 - 配置示例如下所示:108 - 配置示例如下所示:
105 109 
Mexamples/acl/2_sample_resnet50_imagenet_classification_dynmaic_batch/src/sample_resnet50_imagenet_classification_dynamic_batch.cpp+2-1
@@ -95,7 +95,8 @@ Result SampleRes50ImagenetClassification::PrepareModel(const char *modelPath)
95 return SUCCESS;95 return SUCCESS;
96}96}
97 97 
98-void SampleRes50ImagenetClassification::OutputModelResult(uint64_t batchSize) const {98+void SampleRes50ImagenetClassification::OutputModelResult(uint64_t batchSize) const
99+{
99 for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(modelOutput_->GetDataSet()); ++i) {100 for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(modelOutput_->GetDataSet()); ++i) {
100 // Get model output data101 // Get model output data
101 aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(modelOutput_->GetDataSet(), i);102 aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(modelOutput_->GetDataSet(), i);
Rexamples/acl/2_sample_qwen_llm/CMakeLists.txtexamples/acl/3_sample_qwen_llm/CMakeLists.txt+0-0
文件重命名但无更改。
Rexamples/acl/2_sample_qwen_llm/README.mdexamples/acl/3_sample_qwen_llm/README.md+18-14
@@ -27,25 +27,29 @@
27├── CMakeLists.txt // 编译脚本,调用src目录下的CMakeLists文件27├── CMakeLists.txt // 编译脚本,调用src目录下的CMakeLists文件
28```28```
29 29 
30-## 环境要求30+## 环境准备
31- 31+- 通过安装指导 [环境准备](../../../docs/build.md#2-安装软件包)正确安装`toolkit`和`ops`包
32-- 已完成[昇腾AI软件栈在开发环境上的部署](https://www.hiascend.com/document/redirect/CannCommunityInstSoftware)32+- 设置环境变量 (假设包安装在/usr/local/Ascend/)
33+```
34+source /usr/local/Ascend/cann/set_env.sh
35+```
33 36 
34## 实现步骤37## 实现步骤
35 38 
361. 以运行用户登录开发环境。391. 以运行用户登录开发环境。
37 40 
38-2. 下载代码并上传至环境后,请先进入根目录下"examples/acl/2_sample_qwen_llm"样例目录。41+2. 下载代码并上传至环境后,请先进入根目录下"examples/acl/3_sample_qwen_llm"样例目录。
39 42 
40- 请注意,下文中的样例目录均指"examples/acl/2_sample_qwen_llm"目录。43+ 请注意,下文中的样例目录均指"examples/acl/3_sample_qwen_llm"目录。
41 44 
423. 准备Qwen模型。453. 准备Qwen模型。
43- 1. 获取Qwen AIR格式模型。46+ 1. 获取Qwen ONNX格式模型。
44- 
45- 您可以从以下链接中获取Qwen网络的模型文件,并以运行用户将获取的文件上传至开发环境的"样例目录/model"目录下。如果目录不存在,需要自行创建。
46- 
47- - Qwen网络的模型文件(qwen.onnx):单击[Link](https://ascend-cann.obs.cn-north-4.myhuaweicloud.com/cann_test/qwen.onnx)下载该文件。
48 47 
48+ 您可以按照以下命令获取Qwen网络的模型文件,模型文件需要放置到"样例目录/model"目录下。如果目录不存在,需要自行创建。如果wget失败,您也可以直接在浏览器中输入以下链接下载后上传至"样例目录/model"目录。
49+ ```
50+ cd "样例目录/model"
51+ wget https://ascend-cann.obs.cn-north-4.myhuaweicloud.com/cann_test/qwen.onnx
52+ ```
49 2. 将Qwen原始模型转换为适配昇腾AI处理器的离线模型(\*.om文件)。注意如果生成的om文件带有架构后缀(如qwen_linux_aarch64.om),请将文件重命名为qwen.om。53 2. 将Qwen原始模型转换为适配昇腾AI处理器的离线模型(\*.om文件)。注意如果生成的om文件带有架构后缀(如qwen_linux_aarch64.om),请将文件重命名为qwen.om。
50 54 
51 切换到"样例目录/model", 执行模型转换脚本:55 切换到"样例目录/model", 执行模型转换脚本:
@@ -67,7 +71,7 @@
67 71 
68 - --model:原始模型文件路径。72 - --model:原始模型文件路径。
69 - --input_shape:指定模型输入的shape。73 - --input_shape:指定模型输入的shape。
70- - --output:生成的qwen_*.om文件重命名为qwen.om并存放在样例目录/model目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_qwen\_llm.cpp 中的omModelPath参数值。74+ - --output:生成的qwen_*.om文件重命名为qwen.om并存放在"样例目录/model"目录下。建议使用命令中的默认设置,否则在编译代码前,您还需要修改sample\_qwen\_llm.cpp 中的omModelPath参数值。
71 75 
72 ```76 ```
73 ret = sampleQwen.PrepareModel("../model/qwen.om");77 ret = sampleQwen.PrepareModel("../model/qwen.om");
@@ -83,15 +87,15 @@
83 87 
841. 以运行用户登录开发环境。881. 以运行用户登录开发环境。
85 89 
86-2. 请先进入根目录下"examples/acl/2_sample_qwen_llm"样例目录。90+2. 请先进入根目录下"examples/acl/3_sample_qwen_llm"样例目录。
87 91 
88- 请注意,下文中的样例目录均指"examples/acl/2_sample_qwen_llm"目录。92+ 请注意,下文中的样例目录均指"examples/acl/3_sample_qwen_llm"目录。
89 93 
903. 设置环境变量,配置程序编译依赖的头文件与库文件路径。943. 设置环境变量,配置程序编译依赖的头文件与库文件路径。
91 95 
92 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。96 设置以下环境变量后,编译脚本会根据"{DDK_PATH}环境变量值/include/"目录查找编译依赖的头文件,根据{NPU_HOST_LIB}环境变量指向的目录查找编译依赖的库文件。
93 97 
94- **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找Ascend-cann-toolkit安装目录/lib64目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。98+ **注意**,在配置{NPU_HOST_LIB}环境变量时,需使用的"devlib"目录下*.so库,确保在编译基于AscendCL接口的应用程序时,不依赖其它组件(例如Driver)的*.so库,编译成功后,运行应用程序时,系统会根据LD_LIBRARY_PATH环境变量查找"Ascend-cann-toolkit安装目录/lib64"目录下的*.so库,同时会自动链接到所依赖的其它组件的*.so库。
95 99 
96 - 配置示例如下所示:100 - 配置示例如下所示:
97 101 
Rexamples/acl/2_sample_qwen_llm/scripts/build.shexamples/acl/3_sample_qwen_llm/scripts/build.sh+0-0
文件重命名但无更改。
Rexamples/acl/2_sample_qwen_llm/scripts/run.shexamples/acl/3_sample_qwen_llm/scripts/run.sh+0-0
文件重命名但无更改。
Rexamples/acl/2_sample_qwen_llm/src/CMakeLists.txtexamples/acl/3_sample_qwen_llm/src/CMakeLists.txt+0-0
文件重命名但无更改。
Rexamples/acl/2_sample_qwen_llm/src/acl.jsonexamples/acl/3_sample_qwen_llm/src/acl.json+0-0
文件重命名但无更改。
Rexamples/acl/2_sample_qwen_llm/src/sample_qwen_llm.cppexamples/acl/3_sample_qwen_llm/src/sample_qwen_llm.cpp+0-0
文件重命名但无更改。
Aexamples/acl/README.md+9-0
@@ -0,0 +1,9 @@
1+## ES构图样例
2+ 
3+本目录提供了ACL接口相关的各种样例,包括:
4+ 
5+| 样例 | 样例链接 |
6+| --------------------------------------------------------- | ------------------------------------------------------------ |
7+| Resnet50图像识别样例 | [Resnet50](1_sample_resnet50_imagenet_classification/README.md) |
8+| Resnet50图像识别dynmaic batch样例 | [Resnet50 dynmaic batch](2_sample_resnet50_imagenet_classification_dynmaic_batch/README.md) |
9+| Qwen LLM样例 | [Qwen LLM](3_sample_qwen_llm/README.md) |
Mexamples/dflow/python/udf_py_ws_sample/CMakeLists.txt+5-4
@@ -1,11 +1,12 @@
1+# -----------------------------------------------------------------------------------------------------------
1# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
2-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").4+# CANN Open Software License Agreement Version 2.0 (the "License").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10cmake_minimum_required(VERSION 3.14)11cmake_minimum_required(VERSION 3.14)
11 12 
Mexamples/dflow/udf_workspace/03_udf_add_multi_func/CMakeLists.txt+5-4
@@ -1,11 +1,12 @@
1+# -----------------------------------------------------------------------------------------------------------
1# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
2-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").4+# CANN Open Software License Agreement Version 2.0 (the "License").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10cmake_minimum_required(VERSION 3.14)11cmake_minimum_required(VERSION 3.14)
11PROJECT(UDF)12PROJECT(UDF)
Mexamples/dflow/udf_workspace/04_control_func/CMakeLists.txt+4-3
@@ -1,11 +1,12 @@
1+# -----------------------------------------------------------------------------------------------------------
1# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
2-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").4+# CANN Open Software License Agreement Version 2.0 (the "License").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10cmake_minimum_required(VERSION 3.14)11cmake_minimum_required(VERSION 3.14)
11PROJECT(UDF)12PROJECT(UDF)
Mexamples/es/README.md+15-14
@@ -2,17 +2,18 @@
2 2 
3本目录提供了ES构图相关的各种样例,包括C++和Python两种实现方式:3本目录提供了ES构图相关的各种样例,包括C++和Python两种实现方式:
4 4 
5-| 样例 | 样例链接 |5+| 样例 | 样例链接 |
6-| --------------------------------------------------------- | ------------------------------------------------------------ |6+|-------------------|--------------------------------------------------------------------------------------------------------|
7-| es构图控制边样例 | [C++样例](control_edge/cpp/README.md)<br>[Python样例](control_edge/python/README.md) |7+| es构图控制边样例 | [C++样例](control_edge/cpp/README.md)<br>[Python样例](control_edge/python/README.md) |
8-| es构图控制算子样例 | [C++样例](control_op/cpp/README.md)<br>[Python样例](control_op/python/README.md) |8+| es构图控制算子样例 | [C++样例](control_op/cpp/README.md)<br>[Python样例](control_op/python/README.md) |
9-| es构图动态输入样例 | [C++样例](dynamic_input/cpp/README.md)<br>[Python样例](dynamic_input/python/README.md) |9+| es构图动态输入样例 | [C++样例](dynamic_input/cpp/README.md)<br>[Python样例](dynamic_input/python/README.md) |
10-| es构图动态输出样例 | [C++样例](dynamic_output/cpp/README.md)<br>[Python样例](dynamic_output/python/README.md) |10+| es构图动态输出样例 | [C++样例](dynamic_output/cpp/README.md)<br>[Python样例](dynamic_output/python/README.md) |
11-| es构图普通属性样例 | [C++样例](normal_attributes/cpp/README.md)<br>[Python样例](normal_attributes/python/README.md) |11+| es构图普通属性样例 | [C++样例](normal_attributes/cpp/README.md)<br>[Python样例](normal_attributes/python/README.md) |
12-| es构图普通输入样例 | [C++样例](normal_input/cpp/README.md)<br>[Python样例](normal_input/python/README.md) |12+| es构图普通输入样例 | [C++样例](normal_input/cpp/README.md)<br>[Python样例](normal_input/python/README.md) |
13-| es构图操作符重载样例 | [C++样例](operator_overload/cpp/README.md)<br>[Python样例](operator_overload/python/README.md) |13+| es构图操作符重载样例 | [C++样例](operator_overload/cpp/README.md)<br>[Python样例](operator_overload/python/README.md) |
14-| es构图可选输入样例 | [C++样例](optional_input/cpp/README.md)<br>[Python样例](optional_input/python/README.md) |14+| es构图可选输入样例 | [C++样例](optional_input/cpp/README.md)<br>[Python样例](optional_input/python/README.md) |
15-| es构图私有属性样例 | [C++样例](private_attributes/cpp/README.md)<br>[Python样例](private_attributes/python/README.md) |15+| es构图私有属性样例 | [C++样例](private_attributes/cpp/README.md)<br>[Python样例](private_attributes/python/README.md) |
16-| es构图transformer样例 | [C++样例](transformer/cpp/README.md)<br>[Python样例](transformer/python/README.md) |16+| es构图transformer样例 | [C++样例](transformer/cpp/README.md)<br>[Python样例](transformer/python/README.md) |
17-| es构图集合通信hccl_tp样例 | [C++样例](hccl_tp/cpp/README.md)<br>[Python样例](hccl_tp/python/README.md) |17+| es构图集合通信hccl_tp样例 | [C++样例](hccl_tp/cpp/README.md)<br>[Python样例](hccl_tp/python/README.md) |
18-| es构图集合通信hccl_ep样例 | [C++样例](hccl_ep/cpp/README.md)<br>[Python样例](hccl_ep/python/README.md) |18+| es构图集合通信hccl_ep样例 | [C++样例](hccl_ep/cpp/README.md)<br>[Python样例](hccl_ep/python/README.md) |
19+| es构图异步执行的样例 | [C++样例](operator_overload_async/cpp/README.md)<br>[Python样例](operator_overload_async/python/README.md) |
Mexamples/es/operator_overload_async/python/README.md+1-1
@@ -1,7 +1,7 @@
1# 样例使用指导1# 样例使用指导
2 2 
3## 1、功能描述3## 1、功能描述
4-本样例使用操作符重载进行构图,旨在帮助构图开发者快速理解操作符重载的定义,因为python接口暂时**未支持异步执行**,所以本样例仅展示同步执行的构图过程。4+本样例使用操作符重载进行构图,旨在帮助构图开发者快速理解操作符重载的定义,因为python接口暂时**未支持异步执行**,所以本样例**仅展示同步执行**的构图过程。
5## 2、目录结构5## 2、目录结构
6```angular2html6```angular2html
7python/7python/
Mgraph_metadef/register/op_lib_register.cc+4-0
@@ -18,6 +18,7 @@
18#include "graph_metadef/common/plugin/plugin_manager.h"18#include "graph_metadef/common/plugin/plugin_manager.h"
19#include "graph_metadef/graph/utils/file_utils.h"19#include "graph_metadef/graph/utils/file_utils.h"
20 20 
21+extern "C" __attribute__((weak)) void SetMetadefPluginCustomOpLibPathForC(const char* custom_op_Lib_path);
21namespace {22namespace {
22 const std::string custom_so_name = "libcust_opapi.so";23 const std::string custom_so_name = "libcust_opapi.so";
23}24}
@@ -168,6 +169,9 @@ graphStatus OpLibRegistry::CallInitFunc(const std::string &custom_opp_path,
168 op_lib_paths_ += custom_opp_path; // add origin env path to ensure priority(so mode first, runbag mode second)169 op_lib_paths_ += custom_opp_path; // add origin env path to ensure priority(so mode first, runbag mode second)
169 }170 }
170 PluginManager::SetCustomOpLibPath(op_lib_paths_);171 PluginManager::SetCustomOpLibPath(op_lib_paths_);
172+ if (SetMetadefPluginCustomOpLibPathForC != nullptr) {
173+ SetMetadefPluginCustomOpLibPathForC(op_lib_paths_.c_str());
174+ }
171 GELOGI("CallInitFunc %zu successfully, op_lib_paths_ is %s", vendor_funcs_.size(), op_lib_paths_.c_str());175 GELOGI("CallInitFunc %zu successfully, op_lib_paths_ is %s", vendor_funcs_.size(), op_lib_paths_.c_str());
172 return GRAPH_SUCCESS;176 return GRAPH_SUCCESS;
173}177}
Mruntime/v1/CMakeLists.txt+1-0
@@ -312,6 +312,7 @@ target_link_libraries(ge_executor_shared
312 hccl_headers312 hccl_headers
313 $<$<TARGET_EXISTS:datagw_headers>:datagw_headers>313 $<$<TARGET_EXISTS:datagw_headers>:datagw_headers>
314 -Wl,--no-as-needed314 -Wl,--no-as-needed
315+ graph
315 ge_common316 ge_common
316 ge_common_base317 ge_common_base
317 runtime318 runtime
Mruntime/v1/graph/load/model_manager/davinci_model.cc+22-4
@@ -2701,12 +2701,30 @@ void DavinciModel::InitModelInputsMergeCopyHostMem() {
2701 2701 
2702 // init host buff for merge copy, if fail just return and run with no merge copy2702 // init host buff for merge copy, if fail just return and run with no merge copy
2703 input_merge_copy_mem_size_ = last_input.second + last_input_size - first_input.second;2703 input_merge_copy_mem_size_ = last_input.second + last_input_size - first_input.second;
2704- input_merge_copy_mem_base_.reset(new (std::nothrow) uint8_t[input_merge_copy_mem_size_],2704+ void *host_mem = nullptr;
2705- std::default_delete<uint8_t[]>());2705+ const rtError_t rt_ret = rtMallocHost(&host_mem, input_merge_copy_mem_size_, GE_MODULE_NAME_U16);
2706- if (input_merge_copy_mem_base_ == nullptr) {2706+ if (rt_ret != RT_ERROR_NONE) {
2707- GELOGW("[InputMergeCopy][New] host buffer failed, size:%" PRIu64, input_merge_copy_mem_size_);2707+ input_merge_copy_mem_base_.reset();
2708+ GELOGW("[InputMergeCopy][rtMallocHost] host buffer alloc failed, size:%" PRIu64 ", ret:%d",
2709+ input_merge_copy_mem_size_, static_cast<int32_t>(rt_ret));
2708 return;2710 return;
2709 }2711 }
2712+ if (host_mem == nullptr) {
2713+ input_merge_copy_mem_base_.reset();
2714+ GELOGW("[InputMergeCopy][rtMallocHost] host buffer is nullptr, size:%" PRIu64 ", ret:%d",
2715+ input_merge_copy_mem_size_, static_cast<int32_t>(rt_ret));
2716+ return;
2717+ }
2718+ input_merge_copy_mem_base_.reset(static_cast<uint8_t *>(host_mem), [](uint8_t *ptr) {
2719+ if (ptr == nullptr) {
2720+ return;
2721+ }
2722+ const rtError_t free_ret = rtFreeHost(ptr);
2723+ if (free_ret != RT_ERROR_NONE) {
2724+ GELOGW("[InputMergeCopy][rtFreeHost] host buffer free failed, ptr:%p, ret:%d", ptr,
2725+ static_cast<int32_t>(free_ret));
2726+ }
2727+ });
2710 (void)memset_s(input_merge_copy_mem_base_.get(), input_merge_copy_mem_size_, 0U, input_merge_copy_mem_size_);2728 (void)memset_s(input_merge_copy_mem_base_.get(), input_merge_copy_mem_size_, 0U, input_merge_copy_mem_size_);
2711 2729 
2712 // record offset for fusion copy input2730 // record offset for fusion copy input
Mscripts/package/dflow-executor/scripts/dflow-executor_custom_install.sh+4-0
@@ -102,6 +102,10 @@ dflow_executor_install_package() {
102 local _package="$1"102 local _package="$1"
103 local _pythonlocalpath="$2"103 local _pythonlocalpath="$2"
104 log "INFO" "install python module package in ${_package}"104 log "INFO" "install python module package in ${_package}"
105+ if ! command -v pip3 >/dev/null 2>&1; then
106+ log "ERROR" "install ${_package} failed, pip3 is not installed."
107+ exit 1
108+ fi
105 if [ -f "$_package" ]; then109 if [ -f "$_package" ]; then
106 if [ "$pylocal" = "y" ]; then110 if [ "$pylocal" = "y" ]; then
107 pip3 install --disable-pip-version-check --upgrade --no-deps --force-reinstall "${_package}" -t "${_pythonlocalpath}" 1> /dev/null111 pip3 install --disable-pip-version-check --upgrade --no-deps --force-reinstall "${_package}" -t "${_pythonlocalpath}" 1> /dev/null
Mscripts/package/dflow-executor/scripts/run_dflow-executor_upgrade.sh+2-2
@@ -1,10 +1,10 @@
1#!/bin/bash1#!/bin/bash
2# -----------------------------------------------------------------------------------------------------------2# -----------------------------------------------------------------------------------------------------------
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.3# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 4+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5# CANN Open Software License Agreement Version 2.0 (the "License").5# CANN Open Software License Agreement Version 2.0 (the "License").
6# Please refer to the License for details. You may not use this file except in compliance with the License.6# Please refer to the License for details. You may not use this file except in compliance with the License.
7-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9# See LICENSE in the root of the software repository for the full text of the License.9# See LICENSE in the root of the software repository for the full text of the License.
10# -----------------------------------------------------------------------------------------------------------10# -----------------------------------------------------------------------------------------------------------
Mscripts/package/ge-compiler/scripts/ge-compiler_custom_install.sh+4-0
@@ -83,6 +83,10 @@ ge_compiler_install_package() {
83 local _package="$1"83 local _package="$1"
84 local _pythonlocalpath="$2"84 local _pythonlocalpath="$2"
85 log "INFO" "install python module package in ${_package}"85 log "INFO" "install python module package in ${_package}"
86+ if ! command -v pip3 >/dev/null 2>&1; then
87+ log "ERROR" "install ${_package} failed, pip3 is not installed."
88+ exit 1
89+ fi
86 if [ -f "$_package" ]; then90 if [ -f "$_package" ]; then
87 if [ "$pylocal" = "y" ]; then91 if [ "$pylocal" = "y" ]; then
88 pip3 install --disable-pip-version-check --upgrade --no-deps --force-reinstall "${_package}" -t "${_pythonlocalpath}" 1> /dev/null92 pip3 install --disable-pip-version-check --upgrade --no-deps --force-reinstall "${_package}" -t "${_pythonlocalpath}" 1> /dev/null
Mscripts/package/ge-compiler/scripts/run_ge-compiler_upgrade.sh+2-2
@@ -1,10 +1,10 @@
1#!/bin/bash1#!/bin/bash
2# -----------------------------------------------------------------------------------------------------------2# -----------------------------------------------------------------------------------------------------------
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.3# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 4+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5# CANN Open Software License Agreement Version 2.0 (the "License").5# CANN Open Software License Agreement Version 2.0 (the "License").
6# Please refer to the License for details. You may not use this file except in compliance with the License.6# Please refer to the License for details. You may not use this file except in compliance with the License.
7-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
CANN-robot
CANN-robotCANN-robot3月9日
代码可读性: 代码行尾存在多余空格。第7行末尾有一个多余的空格字符,与前一个问题类似,这会影响代码的整洁性。在版权声明等静态文本中保持格式一致很重要。
问题类型: 代码可读性
文件路径: scripts/package/ge-compiler/scripts/run_ge-compiler_upgrade.sh
行号: 7
问题代码:
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
修改建议:
删除行尾的多余空格,保持代码格式一致。
---
此评论由代码审查工具自动生成
likedislike
8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9# See LICENSE in the root of the software repository for the full text of the License.9# See LICENSE in the root of the software repository for the full text of the License.
10# -----------------------------------------------------------------------------------------------------------10# -----------------------------------------------------------------------------------------------------------
Mscripts/package/ge-executor/scripts/run_ge-executor_upgrade.sh+2-2
@@ -1,10 +1,10 @@
1#!/bin/bash1#!/bin/bash
2# -----------------------------------------------------------------------------------------------------------2# -----------------------------------------------------------------------------------------------------------
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.3# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 4+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5# CANN Open Software License Agreement Version 2.0 (the "License").5# CANN Open Software License Agreement Version 2.0 (the "License").
6# Please refer to the License for details. You may not use this file except in compliance with the License.6# Please refer to the License for details. You may not use this file except in compliance with the License.
7-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.8# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
9# See LICENSE in the root of the software repository for the full text of the License.9# See LICENSE in the root of the software repository for the full text of the License.
10# -----------------------------------------------------------------------------------------------------------10# -----------------------------------------------------------------------------------------------------------
Mtests/acl_ut/ut/acl/CMakeLists.txt+1-1
@@ -86,7 +86,7 @@ set(OP_EXEC_SRC_FILES
86 "${BASE_DIR}/api/acl/acl_op_executor/single_op/executor/op_task.cpp"86 "${BASE_DIR}/api/acl/acl_op_executor/single_op/executor/op_task.cpp"
87 "${BASE_DIR}/api/acl/acl_op_executor/types/op_attr.cpp"87 "${BASE_DIR}/api/acl/acl_op_executor/types/op_attr.cpp"
88 "${BASE_DIR}/api/acl/acl_op_executor/types/op_model.cpp"88 "${BASE_DIR}/api/acl/acl_op_executor/types/op_model.cpp"
89- "${BASE_DIR}/api/acl/acl_op_executor/types/acl_op.cpp"89+ "${BASE_DIR}/api/acl/acl_op_executor/types/acl_op_inner.cpp"
90 "${BASE_DIR}/api/acl/common/common_inner.cpp"90 "${BASE_DIR}/api/acl/common/common_inner.cpp"
91 "${BASE_DIR}/api/acl/common/log_inner.cpp"91 "${BASE_DIR}/api/acl/common/log_inner.cpp"
92 "${BASE_DIR}/api/acl/common/json_parser.cpp"92 "${BASE_DIR}/api/acl/common/json_parser.cpp"
Mtests/acl_ut/ut/acl/testcase/acl_utils_unittest.cpp+1-1
@@ -5,7 +5,7 @@
5#include "utils/file_utils.h"5#include "utils/file_utils.h"
6#include "utils/attr_utils.h"6#include "utils/attr_utils.h"
7#include "acl_stub.h"7#include "acl_stub.h"
8-#include "types/acl_op.h"8+#include "types/acl_op_inner.h"
9 9 
10using namespace testing;10using namespace testing;
11using namespace std;11using namespace std;
Mtests/depends/platform/CMakeLists.txt+2-2
@@ -1,9 +1,9 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8# See LICENSE in the root of the software repository for the full text of the License.
9# -----------------------------------------------------------------------------------------------------------9# -----------------------------------------------------------------------------------------------------------
Mtests/depends/runtime/src/runtime_stub.cc+11-1
@@ -651,6 +651,8 @@ void rtStubTearDown() {
651 DEL_STUB_RETURN_VALUE(rtQueryFunctionRegistered, rtError_t);651 DEL_STUB_RETURN_VALUE(rtQueryFunctionRegistered, rtError_t);
652 652 
653 DEL_STUB_RETURN_VALUE(rtMalloc, rtError_t);653 DEL_STUB_RETURN_VALUE(rtMalloc, rtError_t);
654+ DEL_STUB_RETURN_VALUE(rtMallocHost, rtError_t);
655+ DEL_STUB_RETURN_VALUE(rtFreeHost, rtError_t);
654 DEL_STUB_RETURN_VALUE(rtMemcpy, rtError_t);656 DEL_STUB_RETURN_VALUE(rtMemcpy, rtError_t);
655 DEL_STUB_RETURN_VALUE(rtsMemcpyBatch, rtError_t);657 DEL_STUB_RETURN_VALUE(rtsMemcpyBatch, rtError_t);
656 DEL_STUB_RETURN_VALUE(rtDatadumpInfoLoad, rtError_t);658 DEL_STUB_RETURN_VALUE(rtDatadumpInfoLoad, rtError_t);
@@ -853,14 +855,22 @@ rtError_t rtFree(void *dev_ptr) {
853 return ge::RuntimeStub::GetInstance()->rtFree(dev_ptr);855 return ge::RuntimeStub::GetInstance()->rtFree(dev_ptr);
854}856}
855 857 
858+ADD_STUB_RETURN_VALUE(rtMallocHost, rtError_t);
856rtError_t rtMallocHost(void **host_ptr, uint64_t size, uint16_t moduleId) {859rtError_t rtMallocHost(void **host_ptr, uint64_t size, uint16_t moduleId) {
860+ const rtError_t ret = GET_STUB_RETURN_VALUE(rtMallocHost, rtError_t, RT_ERROR_NONE);
861+ if (ret != RT_ERROR_NONE) {
862+ *host_ptr = nullptr;
863+ return ret;
864+ }
857 *host_ptr = new uint8_t[size];865 *host_ptr = new uint8_t[size];
858 return RT_ERROR_NONE;866 return RT_ERROR_NONE;
859}867}
860 868 
869+ADD_STUB_RETURN_VALUE(rtFreeHost, rtError_t);
861rtError_t rtFreeHost(void *host_ptr) {870rtError_t rtFreeHost(void *host_ptr) {
871+ const rtError_t ret = GET_STUB_RETURN_VALUE(rtFreeHost, rtError_t, RT_ERROR_NONE);
862 delete[](uint8_t *) host_ptr;872 delete[](uint8_t *) host_ptr;
863- return RT_ERROR_NONE;873+ return ret;
864}874}
865 875 
866rtError_t rtStreamCreate(rtStream_t *stream, int32_t priority) {876rtError_t rtStreamCreate(rtStream_t *stream, int32_t priority) {
Mtests/depends/runtime/src/runtime_stub.h+2-0
@@ -468,6 +468,8 @@ RTS_STUB_RETURN_EXTERN(rtNpuGetFloatStatus, rtError_t);
468RTS_STUB_RETURN_EXTERN(rtNpuClearFloatStatus, rtError_t);468RTS_STUB_RETURN_EXTERN(rtNpuClearFloatStatus, rtError_t);
469 469 
470RTS_STUB_RETURN_EXTERN(rtMalloc, rtError_t);470RTS_STUB_RETURN_EXTERN(rtMalloc, rtError_t);
471+RTS_STUB_RETURN_EXTERN(rtMallocHost, rtError_t);
472+RTS_STUB_RETURN_EXTERN(rtFreeHost, rtError_t);
471RTS_STUB_RETURN_EXTERN(rtMemcpy, rtError_t);473RTS_STUB_RETURN_EXTERN(rtMemcpy, rtError_t);
472RTS_STUB_RETURN_EXTERN(rtsMemcpyBatch, rtError_t);474RTS_STUB_RETURN_EXTERN(rtsMemcpyBatch, rtError_t);
473RTS_STUB_RETURN_EXTERN(rtDatadumpInfoLoad, rtError_t);475RTS_STUB_RETURN_EXTERN(rtDatadumpInfoLoad, rtError_t);
Mtests/dflow/flow_graph/CMakeLists.txt+5-3
@@ -1,9 +1,11 @@
1+# -----------------------------------------------------------------------------------------------------------
1# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
2-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").4+# CANN Open Software License Agreement Version 2.0 (the "License").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
10+ 
9add_subdirectory(ut)11add_subdirectory(ut)
Mtests/dflow/flow_graph/ut/CMakeLists.txt+5-4
@@ -1,11 +1,12 @@
1-# Copyright (c) 2024 Huawei Technologies Co., Ltd.1+# -----------------------------------------------------------------------------------------------------------
2-# This file is a part of the CANN Open Software.2+# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").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").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10if (ENABLE_GE_COV)11if (ENABLE_GE_COV)
11 set(COVERAGE_COMPILER_FLAGS ${AIR_COMMON_COMPILE_OPTION})12 set(COVERAGE_COMPILER_FLAGS ${AIR_COMMON_COMPILE_OPTION})
Mtests/engines/rts_engine/CMakeLists.txt+5-4
@@ -1,11 +1,12 @@
1-# Copyright (c) 2024 Huawei Technologies Co., Ltd.1+# -----------------------------------------------------------------------------------------------------------
2-# This file is a part of the CANN Open Software.2+# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").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").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10if (ENABLE_LLT_COV)11if (ENABLE_LLT_COV)
11 set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -fPIC -O0 -ftest-coverage")12 set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-arcs -fPIC -O0 -ftest-coverage")
Mtests/engines/rts_engine/ut/CMakeLists.txt+5-4
@@ -1,11 +1,12 @@
1-# Copyright (c) 2024 Huawei Technologies Co., Ltd.1+# -----------------------------------------------------------------------------------------------------------
2-# This file is a part of the CANN Open Software.2+# Copyright (c) 2025 Huawei Technologies Co., Ltd.
3-# Licensed under CANN Open Software License Agreement Version 1.0 (the "License").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").
4# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
5# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,6# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7# See LICENSE in the root of the software repository for the full text of the License.8# See LICENSE in the root of the software repository for the full text of the License.
8-# ======================================================================================================================9+# -----------------------------------------------------------------------------------------------------------
9 10 
10set(proto_src_files11set(proto_src_files
11 ${METADEF_PROTO_DIR}/task.proto12 ${METADEF_PROTO_DIR}/task.proto
Mtests/ge/ut/ge/graph/eager_style_graph_builder/es_generator/gen_impl_unittest.cc+2-2
@@ -1,9 +1,9 @@
1/**1/**
2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3- * This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
Mtests/ge/ut/ge/graph/eager_style_graph_builder/es_generator/py_generator_unittest.cc+2-2
@@ -1,9 +1,9 @@
1/**1/**
2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.2 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3- * This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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.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, 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.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.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
Mtests/ge/ut/ge/graph/load/davinci_model_unittest.cc+75-0
@@ -7505,6 +7505,81 @@ TEST_F(UtestDavinciModel, InputMergeCopy) {
7505 ge::GetThreadLocalContext().SetGraphOption({}); // restore option7505 ge::GetThreadLocalContext().SetGraphOption({}); // restore option
7506}7506}
7507 7507 
7508+TEST_F(UtestDavinciModel, InitModelInputsMergeCopyHostMem_rtMallocHost_fail) {
7509+ RTS_STUB_RETURN_VALUE(rtMallocHost, rtError_t, ACL_ERROR_RT_PARAM_INVALID);
7510+ const uint64_t input_fusion_size = 25600U;
7511+ const uint64_t start_logic_addr = 30902000U; // random value for test
7512+ std::map<std::string, std::string> options_map;
7513+ options_map[OPTION_EXEC_INPUT_FUSION_SIZE] = std::to_string(input_fusion_size);
7514+ ge::GetThreadLocalContext().SetGraphOption(options_map);
7515+ 
7516+ const uint64_t input0_size = input_fusion_size - 1U;
7517+ const uint64_t input1_size = input_fusion_size;
7518+ 
7519+ DavinciModel davinci_model(0, nullptr);
7520+ davinci_model.zero_copy_input_indexes_.emplace_back(0);
7521+ davinci_model.zero_copy_input_indexes_.emplace_back(1);
7522+ davinci_model.input_index_to_allocation_ids_.emplace_back(0);
7523+ davinci_model.input_index_to_allocation_ids_.emplace_back(1);
7524+ 
7525+ MemAllocation mem_allocation0 = {};
7526+ mem_allocation0.data_size = input0_size + 32U;
7527+ mem_allocation0.tensor_size = input0_size;
7528+ mem_allocation0.logical_addr = start_logic_addr;
7529+ 
7530+ MemAllocation mem_allocation1;
7531+ mem_allocation1.data_size = input1_size + 32U;
7532+ mem_allocation1.tensor_size = input1_size;
7533+ mem_allocation1.logical_addr = start_logic_addr - mem_allocation1.data_size;
7534+ 
7535+ davinci_model.logical_mem_allocations_.emplace_back(mem_allocation0);
7536+ davinci_model.logical_mem_allocations_.emplace_back(mem_allocation1);
7537+ 
7538+ davinci_model.InitModelInputsMergeCopyHostMem();
7539+ EXPECT_EQ(davinci_model.input_merge_copy_mem_base_, nullptr);
7540+ EXPECT_TRUE(davinci_model.input_index_to_merge_copy_offset_.empty());
7541+ ge::GetThreadLocalContext().SetGraphOption({});
7542+}
7543+ 
7544+TEST_F(UtestDavinciModel, InitModelInputsMergeCopyHostMem_rtFreeHost_fail) {
7545+ const uint64_t input_fusion_size = 25600U;
7546+ const uint64_t start_logic_addr = 30902000U; // random value for test
7547+ std::map<std::string, std::string> options_map;
7548+ options_map[OPTION_EXEC_INPUT_FUSION_SIZE] = std::to_string(input_fusion_size);
7549+ ge::GetThreadLocalContext().SetGraphOption(options_map);
7550+ 
7551+ const uint64_t input0_size = input_fusion_size - 1U;
7552+ const uint64_t input1_size = input_fusion_size;
7553+ 
7554+ DavinciModel davinci_model(0, nullptr);
7555+ davinci_model.zero_copy_input_indexes_.emplace_back(0);
7556+ davinci_model.zero_copy_input_indexes_.emplace_back(1);
7557+ davinci_model.input_index_to_allocation_ids_.emplace_back(0);
7558+ davinci_model.input_index_to_allocation_ids_.emplace_back(1);
7559+ 
7560+ MemAllocation mem_allocation0 = {};
7561+ mem_allocation0.data_size = input0_size + 32U;
7562+ mem_allocation0.tensor_size = input0_size;
7563+ mem_allocation0.logical_addr = start_logic_addr;
7564+ 
7565+ MemAllocation mem_allocation1;
7566+ mem_allocation1.data_size = input1_size + 32U;
7567+ mem_allocation1.tensor_size = input1_size;
7568+ mem_allocation1.logical_addr = start_logic_addr - mem_allocation1.data_size;
7569+ 
7570+ davinci_model.logical_mem_allocations_.emplace_back(mem_allocation0);
7571+ davinci_model.logical_mem_allocations_.emplace_back(mem_allocation1);
7572+ 
7573+ davinci_model.InitModelInputsMergeCopyHostMem();
7574+ EXPECT_NE(davinci_model.input_merge_copy_mem_base_, nullptr);
7575+ EXPECT_EQ(davinci_model.input_index_to_merge_copy_offset_.size(), 2U);
7576+ 
7577+ RTS_STUB_RETURN_VALUE(rtFreeHost, rtError_t, ACL_ERROR_RT_PARAM_INVALID);
7578+ davinci_model.input_merge_copy_mem_base_.reset();
7579+ EXPECT_EQ(davinci_model.input_merge_copy_mem_base_, nullptr);
7580+ ge::GetThreadLocalContext().SetGraphOption({});
7581+}
7582+ 
7508TEST_F(UtestDavinciModel, GenInputMemAllocations_InValid) {7583TEST_F(UtestDavinciModel, GenInputMemAllocations_InValid) {
7509 DavinciModel davinci_model(0, nullptr);7584 DavinciModel davinci_model(0, nullptr);
7510 std::map<uint32_t, OpDescPtr> index_to_data;7585 std::map<uint32_t, OpDescPtr> index_to_data;