已合并
feat: 【编译性能优化】TilingFunc支持按需引用头文件 #1530
feat: 【编译性能优化】TilingFunc支持按需引用头文件 #1530
已合并
zhang_shengjie创建于 7月28日
47 个文件变更+3217-2224
@@ -110,10 +110,20 @@ const std::string kIsTrue = "1";
110const std::string kIsFalse = "0";110const std::string kIsFalse = "0";
111const std::string kTilingFuncIdentify = "TilingFunc";111const std::string kTilingFuncIdentify = "TilingFunc";
112const std::string kTilingHeadIdentify = "TilingHead";112const std::string kTilingHeadIdentify = "TilingHead";
113+const std::string kTilingStateHeaderIdentify = "TilingStateHeader";
114+const std::string kTilingLogHeaderIdentify = "TilingLogHeader";
115+const std::string kTilingPgoHeaderIdentify = "TilingPgoHeader";
116+const std::string kTilingSolverHeaderIdentify = "TilingSolverHeader";
117+const std::string kTilingApiHeaderIdentify = "TilingApiHeader";
113const std::string kTilingSolverIdentify = "solver_func";118const std::string kTilingSolverIdentify = "solver_func";
114const std::string kTilingScheduleGroupTailIdentify = "schedule_group_tail";119const std::string kTilingScheduleGroupTailIdentify = "schedule_group_tail";
115const std::string kDefaultTilingDataFileName = "tiling_data.h";120const std::string kDefaultTilingDataFileName = "tiling_data.h";
116const std::string kDefaultTilingHeadFileName = "autofuse_tiling_func_common.h";121const std::string kDefaultTilingHeadFileName = "autofuse_tiling_func_common.h";
122+const std::string kTilingStateHeaderFileName = "autofuse_tiling_func_state.h";
123+const std::string kTilingLogHeaderFileName = "autofuse_tiling_func_log.h";
124+const std::string kTilingPgoHeaderFileName = "autofuse_tiling_func_pgo.h";
125+const std::string kTilingSolverHeaderFileName = "autofuse_tiling_func_solver.h";
126+const std::string kTilingApiHeaderFileName = "autofuse_tiling_func_api.h";
117const std::string kDefaultTilingFuncFileName = "tiling_func.cpp";127const std::string kDefaultTilingFuncFileName = "tiling_func.cpp";
118const std::string kHighPrecision = "high_precision";128const std::string kHighPrecision = "high_precision";
119const std::string kDurationLevelName = "duration_level";129const std::string kDurationLevelName = "duration_level";
@@ -463,6 +463,8 @@ af::Status GetConfusionTransposeTilingHeadFiles([[maybe_unused]] const std::stri
463#include <array>463#include <array>
464#include "graph/tensor.h"464#include "graph/tensor.h"
465 465 
466+#ifndef AUTOFUSE_CONFUSION_TRANSPOSE_TILING_DEFS
467+#define AUTOFUSE_CONFUSION_TRANSPOSE_TILING_DEFS
466using graphStatus = uint32_t;468using graphStatus = uint32_t;
467const graphStatus GRAPH_FAILED = 0xFFFFFFFF;469const graphStatus GRAPH_FAILED = 0xFFFFFFFF;
468const graphStatus GRAPH_SUCCESS = 0;470const graphStatus GRAPH_SUCCESS = 0;
@@ -479,6 +481,7 @@ enum class AutoFuseTransposeType: uint8_t {
479 TRANSPOSE_ND2ND_0321 = 6,481 TRANSPOSE_ND2ND_0321 = 6,
480 TRANSPOSE_INVALID = 7482 TRANSPOSE_INVALID = 7
481};483};
484+#endif
482)";485)";
483 486 
484 code_string = kHeaderContent;487 code_string = kHeaderContent;
@@ -80,14 +80,22 @@ void AxesReorderTilingCodeGenImpl::ConfigureSolverPassManagerCommon(SolverPassMa
80}80}
81 81 
82af::Status AxesReorderTilingCodeGenImpl::GenSolverBaseClass() {82af::Status AxesReorderTilingCodeGenImpl::GenSolverBaseClass() {
83+ auto &solver_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kSolver].dependencies;
84+ for (const auto &header : {"cstddef", "sstream", "utility", "vector"}) {
85+ autofuse::RequireSystemHeader(solver_dependencies, header);
86+ }
83 const bool is_enable_equal_order_tiling = IsAnyModelEnableEqualOrderTiling(tiling_model_info_);87 const bool is_enable_equal_order_tiling = IsAnyModelEnableEqualOrderTiling(tiling_model_info_);
88+ if (is_enable_equal_order_tiling) {
89+ RequireTranslationUnitSystemHeader("limits");
90+ RequireTranslationUnitSystemHeader("map");
91+ }
84 std::string basic_solvers_head = SolverPassManager::GenAxesReorderBaseClassesHead(is_enable_equal_order_tiling);92 std::string basic_solvers_head = SolverPassManager::GenAxesReorderBaseClassesHead(is_enable_equal_order_tiling);
85- tiling_head_.AddLine(basic_solvers_head);93+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kSolver, basic_solvers_head);
86 std::string basic_solvers_func = SolverPassManager::GenAxesReorderBaseClassesFunc(is_enable_equal_order_tiling);94 std::string basic_solvers_func = SolverPassManager::GenAxesReorderBaseClassesFunc(is_enable_equal_order_tiling);
87 tiling_func_.AddLine(basic_solvers_func);95 tiling_func_.AddLine(basic_solvers_func);
88 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {96 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
89 std::string pgo_solver_head = SolverPassManager::GenAxesReorderPgoClassesHead(config_.pgo_step_max);97 std::string pgo_solver_head = SolverPassManager::GenAxesReorderPgoClassesHead(config_.pgo_step_max);
90- tiling_head_.AddLine(pgo_solver_head);98+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kSolver, pgo_solver_head);
91 std::string pgo_solver_func = SolverPassManager::GenAxesReorderPgoClassesFunc();99 std::string pgo_solver_func = SolverPassManager::GenAxesReorderPgoClassesFunc();
92 tiling_func_.AddLine(pgo_solver_func);100 tiling_func_.AddLine(pgo_solver_func);
93 }101 }
@@ -59,6 +59,48 @@ std::string GenShapeKeyToStringCode(const std::string &key_name) {
59 ss << "}.operator()().c_str()";59 ss << "}.operator()().c_str()";
60 return ss.str();60 return ss.str();
61}61}
62+ 
63+std::string GenOperatorCacheLog(const std::string &message, const std::string &key_name) {
64+ if (key_name.empty()) {
65+ return " OP_LOGD(OP_NAME, \"[Operator Cache] " + message + " key=[]\");";
66+ }
67+ return " OP_LOGD(OP_NAME, \"[Operator Cache] " + message + " key=[%s]\", " + GenShapeKeyToStringCode(key_name) +
68+ ");";
69+}
70+ 
71+std::string GenOperatorCacheAgingLog(const std::string &cache_context, const std::string &key_name) {
72+ const std::string min_count = cache_context + "::GetLastAgedMinCount()";
73+ if (key_name.empty()) {
74+ return " OP_LOGD(OP_NAME, \"[Operator Cache] CACHE CLEARED AND SAVE SUCCESS: min_count=%lu, key=[]\", " +
75+ min_count + ");";
76+ }
77+ return " OP_LOGD(OP_NAME, \"[Operator Cache] CACHE CLEARED AND SAVE SUCCESS: min_count=%lu, key=[%s]\", " +
78+ min_count + ", " + GenShapeKeyToStringCode(key_name) + ");";
79+}
80+ 
81+void GenCacheQueryCode(ge::CodePrinter &code_printer, const std::string &cache_context, const std::string &key_name) {
82+ code_printer.AddLine(" auto *cached_tiling_data = " + cache_context + "::FindOperatorCache(input_shapes);");
83+ code_printer.AddLine(" if (cached_tiling_data != nullptr) {");
84+ code_printer.AddLine(" memcpy(&tiling_data, cached_tiling_data, sizeof(tiling_data));");
85+ code_printer.AddLine(GenOperatorCacheLog("HIT!", key_name));
86+ code_printer.AddLine(" return true;");
87+ code_printer.AddLine(" }");
88+ code_printer.AddLine(GenOperatorCacheLog("MISS!", key_name));
89+ code_printer.AddLine("");
90+}
91+ 
92+void GenCacheSaveCode(ge::CodePrinter &code_printer, const std::string &cache_context, const std::string &key_name) {
93+ const std::string shape_key = key_name.empty() ? "empty_shapes" : key_name;
94+ code_printer.AddLine(" const auto cache_save_result = " + cache_context + "::SaveOperatorCache(" + shape_key +
95+ ", tiling_data);");
96+ code_printer.AddLine(" if (cache_save_result == OperatorCacheSaveResult::kSaved) {");
97+ code_printer.AddLine(GenOperatorCacheLog("SAVE SUCCESS:", key_name));
98+ code_printer.AddLine(" } else if (cache_save_result == OperatorCacheSaveResult::kClearedAndSaved) {");
99+ code_printer.AddLine(GenOperatorCacheAgingLog(cache_context, key_name));
100+ code_printer.AddLine(" } else if (cache_save_result == OperatorCacheSaveResult::kFailed) {");
101+ code_printer.AddLine(GenOperatorCacheLog("SAVE FAILED:", key_name));
102+ code_printer.AddLine(" }");
103+}
62} // namespace104} // namespace
63 105 
64af::Status OperatorLevelCacheGen::GenFixedSizeHashMapDef(ge::CodePrinter &code_printer) {106af::Status OperatorLevelCacheGen::GenFixedSizeHashMapDef(ge::CodePrinter &code_printer) {
@@ -68,32 +110,19 @@ af::Status OperatorLevelCacheGen::GenFixedSizeHashMapDef(ge::CodePrinter &code_p
68 return af::SUCCESS;110 return af::SUCCESS;
69}111}
70 112 
71-af::Status OperatorLevelCacheGen::GenTilingCacheContext(ge::CodePrinter &code_printer,113+af::Status OperatorLevelCacheGen::GenTilingCacheContext(ge::CodePrinter &code_printer) {
72- const std::string &tiling_data_type_name) {
73 // 生成TilingCacheContext类114 // 生成TilingCacheContext类
74- std::string context_class = GenContextClass(tiling_data_type_name);115+ std::string context_class = GenContextClass();
75 code_printer.AddLine(context_class);116 code_printer.AddLine(context_class);
76 code_printer.AddLine("");117 code_printer.AddLine("");
77 return af::SUCCESS;118 return af::SUCCESS;
78}119}
79 120 
80-af::Status OperatorLevelCacheGen::GenTilingCacheContextStaticDefs(ge::CodePrinter &code_printer) {121+af::Status OperatorLevelCacheGen::GenOperatorCacheTypes(ge::CodePrinter &code_printer) {
81- // 生成TilingCacheContext静态成员变量定义(必须在cpp文件中)
82- code_printer.AddLine(R"(
83-// TilingCacheContext 静态成员变量定义
84-thread_local std::unique_ptr<OperatorLevelCache> TilingCacheContext::operator_cache_;
85-thread_local bool TilingCacheContext::initialized_ = false;
86-thread_local std::array<uint64_t, kOperatorCacheCapacity> TilingCacheContext::access_counts_;
87- 
88-)");
89- return af::SUCCESS;
90-}
91- 
92-af::Status OperatorLevelCacheGen::GenOperatorCacheTypes(ge::CodePrinter &code_printer,
93- const std::string &tiling_data_type_name) {
94 // 第一级:算子级缓存(使用kInputShapeSize)122 // 第一级:算子级缓存(使用kInputShapeSize)
95- code_printer.AddLine("using OperatorLevelCache = FixedSizeHashMap<kInputShapeSize, kOperatorCacheCapacity, " +123+ code_printer.AddLine("template <typename TilingData>");
96- tiling_data_type_name + ">;");124+ code_printer.AddLine(
125+ "using OperatorLevelCache = FixedSizeHashMap<kInputShapeSize, kOperatorCacheCapacity, TilingData>;");
97 code_printer.AddLine("");126 code_printer.AddLine("");
98 127 
99 return af::SUCCESS;128 return af::SUCCESS;
@@ -104,8 +133,8 @@ af::Status OperatorLevelCacheGen::GenOperatorCacheFunctions(ge::CodePrinter &cod
104 // 生成算子级缓存函数(使用R"()"格式以提高性能)133 // 生成算子级缓存函数(使用R"()"格式以提高性能)
105 std::string find_func = R"(134 std::string find_func = R"(
106bool FindOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, )" +135bool FindOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, )" +
107- tiling_data_type_name +136+ tiling_data_type_name + R"(& tiling_data, OperatorLevelCache<)" + tiling_data_type_name +
108- R"(& tiling_data, OperatorLevelCache& cache) {137+ R"(>& cache) {
109 const auto* result = cache.Find(input_shapes);138 const auto* result = cache.Find(input_shapes);
110 if (result != nullptr) {139 if (result != nullptr) {
111 tiling_data = *result;140 tiling_data = *result;
@@ -117,8 +146,8 @@ bool FindOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, )" +
117 146 
118 std::string save_func = R"(147 std::string save_func = R"(
119bool SaveOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, const )" +148bool SaveOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, const )" +
120- tiling_data_type_name +149+ tiling_data_type_name + R"(& tiling_data, OperatorLevelCache<)" + tiling_data_type_name +
121- R"(& tiling_data, OperatorLevelCache& cache) {150+ R"(>& cache) {
122 return cache.Insert(input_shapes, tiling_data);151 return cache.Insert(input_shapes, tiling_data);
123}152}
124)";153)";
@@ -142,12 +171,10 @@ af::Status OperatorLevelCacheGen::GenSaveCacheCalls(ge::CodePrinter &code_printe
142 tiling_model_info[0].graph_name.c_str());171 tiling_model_info[0].graph_name.c_str());
143 code_printer.AddLine(" // 静态Shape场景:使用空key缓存");172 code_printer.AddLine(" // 静态Shape场景:使用空key缓存");
144 code_printer.AddLine(" std::array<uint32_t, kInputShapeSize> empty_shapes = {};");173 code_printer.AddLine(" std::array<uint32_t, kInputShapeSize> empty_shapes = {};");
145- // 缓存保存失败不影响GetTiling的整体结果,所以直接调用而不使用ret |=174+ GenCacheSaveCode(code_printer, "TilingCacheContext<" + config.tiling_data_type_name + ">", "");
146- code_printer.AddLine(" (void)TilingCacheContext::SaveOperatorCache(empty_shapes, tiling_data);");
147 return af::SUCCESS;175 return af::SUCCESS;
148 }176 }
149- // 缓存保存失败不影响GetTiling的整体结果,所以直接调用而不使用ret |=177+ GenCacheSaveCode(code_printer, "TilingCacheContext<" + config.tiling_data_type_name + ">", "input_shapes");
150- code_printer.AddLine(" (void)TilingCacheContext::SaveOperatorCache(input_shapes, tiling_data);");
151 return af::SUCCESS;178 return af::SUCCESS;
152}179}
153 180 
@@ -157,6 +184,7 @@ af::Status OperatorLevelCacheGen::GenInitAndQueryCacheCode(ge::CodePrinter &code
157 if (!config.cache_enabled_at_compile_time) {184 if (!config.cache_enabled_at_compile_time) {
158 return af::SUCCESS;185 return af::SUCCESS;
159 }186 }
187+ const std::string cache_context = "TilingCacheContext<" + config.tiling_data_type_name + ">";
160 const auto var_accessors = GetVarAccessors(tiling_model_info);188 const auto var_accessors = GetVarAccessors(tiling_model_info);
161 if (var_accessors.empty()) {189 if (var_accessors.empty()) {
162 // 静态Shape场景:使用空key进行缓存查询190 // 静态Shape场景:使用空key进行缓存查询
@@ -164,13 +192,7 @@ af::Status OperatorLevelCacheGen::GenInitAndQueryCacheCode(ge::CodePrinter &code
164 tiling_model_info[0].graph_name.c_str());192 tiling_model_info[0].graph_name.c_str());
165 code_printer.AddLine(" // 静态Shape场景:算子级缓存查询(空key)");193 code_printer.AddLine(" // 静态Shape场景:算子级缓存查询(空key)");
166 code_printer.AddLine(" std::array<uint32_t, kInputShapeSize> input_shapes = {};");194 code_printer.AddLine(" std::array<uint32_t, kInputShapeSize> input_shapes = {};");
167- code_printer.AddLine(" if (TilingCacheContext::FindOperatorCache(input_shapes) != nullptr) {");195+ GenCacheQueryCode(code_printer, cache_context, "");
168- code_printer.AddLine(
169- " memcpy(&tiling_data, TilingCacheContext::FindOperatorCache(input_shapes), sizeof(tiling_data));");
170- code_printer.AddLine(" OP_LOGI(OP_NAME, \"Operator level cache hit (static shape)\");");
171- code_printer.AddLine(" return true;");
172- code_printer.AddLine(" }");
173- code_printer.AddLine("");
174 return af::SUCCESS;196 return af::SUCCESS;
175 }197 }
176 198 
@@ -185,30 +207,29 @@ af::Status OperatorLevelCacheGen::GenInitAndQueryCacheCode(ge::CodePrinter &code
185 array_init += "};";207 array_init += "};";
186 code_printer.AddLine(array_init);208 code_printer.AddLine(array_init);
187 209 
188- code_printer.AddLine(" if (TilingCacheContext::FindOperatorCache(input_shapes) != nullptr) {");210+ GenCacheQueryCode(code_printer, cache_context, "input_shapes");
189- code_printer.AddLine(
190- " memcpy(&tiling_data, TilingCacheContext::FindOperatorCache(input_shapes), sizeof(tiling_data));");
191- code_printer.AddLine(std::string(" OP_LOGI(OP_NAME, \"Operator level cache hit, input_shapes[%s]\", ") +
192- GenShapeKeyToStringCode("input_shapes") + ");");
193- code_printer.AddLine(" return true;");
194- code_printer.AddLine(" }");
195- code_printer.AddLine("");
196 211 
197 return af::SUCCESS;212 return af::SUCCESS;
198}213}
199 214 
200-std::string OperatorLevelCacheGen::GenContextClass(const std::string &tiling_data_type_name) {215+std::string OperatorLevelCacheGen::GenContextClass() {
201 std::stringstream ss;216 std::stringstream ss;
202 217 
203 ss << R"(218 ss << R"(
219+enum class OperatorCacheSaveResult {
220+ kSaved,
221+ kClearedAndSaved,
222+ kFailed,
223+};
224+ 
204/**225/**
205 * @brief Tiling缓存上下文类226 * @brief Tiling缓存上下文类
206 * 线程级别的缓存上下文,使用thread_local存储,无需线程ID227 * 线程级别的缓存上下文,使用thread_local存储,无需线程ID
207 */228 */
229+template <typename TilingData>
208class TilingCacheContext {230class TilingCacheContext {
209)" << GenContextClassStructure()231)" << GenContextClassStructure()
210- << GenContextClassPublicMethods() << GenContextCacheOperations(tiling_data_type_name) << GenContextHashFunction()232+ << GenContextClassPublicMethods() << GenContextCacheOperations() << GenContextHashFunction() << R"(
211- << R"(
212};233};
213)";234)";
214 235 
@@ -222,10 +243,11 @@ std::string OperatorLevelCacheGen::GenContextClassStructure() {
222private:243private:
223 // 第一级:算子级缓存(thread_local,使用unique_ptr避免栈溢出)244 // 第一级:算子级缓存(thread_local,使用unique_ptr避免栈溢出)
224 // 注意:使用kInputShapeSize大小的key,以支持不同数量的输入变量245 // 注意:使用kInputShapeSize大小的key,以支持不同数量的输入变量
225- static thread_local std::unique_ptr<OperatorLevelCache> operator_cache_;246+ inline static thread_local std::unique_ptr<OperatorLevelCache<TilingData>> operator_cache_;
226- static thread_local bool initialized_;247+ inline static thread_local bool initialized_ = false;
227 // 访问计数(用于LRU老化)248 // 访问计数(用于LRU老化)
228- static thread_local std::array<uint64_t, kOperatorCacheCapacity> access_counts_;249+ inline static thread_local std::array<uint64_t, kOperatorCacheCapacity> access_counts_;
250+ inline static thread_local uint64_t last_aged_min_count_ = 0;
229)";251)";
230 252 
231 return ss.str();253 return ss.str();
@@ -238,14 +260,15 @@ std::string OperatorLevelCacheGen::GenContextClassPublicMethods() {
238public:260public:
239 261 
240 // 获取算子级缓存实例262 // 获取算子级缓存实例
241- static OperatorLevelCache& GetOperatorCache() {263+ static OperatorLevelCache<TilingData>& GetOperatorCache() {
242 if (!initialized_) {264 if (!initialized_) {
243 initialized_ = true;265 initialized_ = true;
244- operator_cache_ = std::make_unique<OperatorLevelCache>();266+ operator_cache_ = std::make_unique<OperatorLevelCache<TilingData>>();
245 // 初始化访问计数267 // 初始化访问计数
246 for (size_t i = 0; i < kOperatorCacheCapacity; ++i) {268 for (size_t i = 0; i < kOperatorCacheCapacity; ++i) {
247 access_counts_[i] = 0;269 access_counts_[i] = 0;
248 }270 }
271+ last_aged_min_count_ = 0;
249 }272 }
250 return *operator_cache_;273 return *operator_cache_;
251 }274 }
@@ -255,30 +278,29 @@ public:
255 operator_cache_.reset();278 operator_cache_.reset();
256 initialized_ = false;279 initialized_ = false;
257 }280 }
281+ 
282+ static uint64_t GetLastAgedMinCount() {
283+ return last_aged_min_count_;
284+ }
258)";285)";
259 286 
260 return ss.str();287 return ss.str();
261}288}
262 289 
263-std::string OperatorLevelCacheGen::GenFindOperatorCacheImpl(const std::string &tiling_data_type_name) {290+std::string OperatorLevelCacheGen::GenFindOperatorCacheImpl() {
264 std::stringstream ss;291 std::stringstream ss;
265 ss << R"(292 ss << R"(
266 // 查询算子级缓存(更新访问计数)293 // 查询算子级缓存(更新访问计数)
267 static )"294 static )"
268- << tiling_data_type_name << R"(* FindOperatorCache(const std::array<uint32_t, kInputShapeSize>& shape_key) {295+ << "TilingData" << R"(* FindOperatorCache(const std::array<uint32_t, kInputShapeSize>& shape_key) {
269 )"296 )"
270- << tiling_data_type_name297+ << "TilingData"
271 << R"(* result = GetOperatorCache().Find(shape_key);298 << R"(* result = GetOperatorCache().Find(shape_key);
272 if (result != nullptr) {299 if (result != nullptr) {
273- OP_LOGI(OP_NAME, "[Operator Cache] HIT! key=[%s]", )" +
274- GenShapeKeyToStringCode("shape_key") + R"();
275 // 更新访问计数300 // 更新访问计数
276 size_t hash = Hash(shape_key);301 size_t hash = Hash(shape_key);
277 size_t index = hash % kOperatorCacheCapacity;302 size_t index = hash % kOperatorCacheCapacity;
278 access_counts_[index]++;303 access_counts_[index]++;
279- } else {
280- OP_LOGI(OP_NAME, "[Operator Cache] MISS! key=[%s]", )" +
281- GenShapeKeyToStringCode("shape_key") + R"();
282 }304 }
283 return result;305 return result;
284 }306 }
@@ -286,59 +308,53 @@ std::string OperatorLevelCacheGen::GenFindOperatorCacheImpl(const std::string &t
286 return ss.str();308 return ss.str();
287}309}
288 310 
289-std::string OperatorLevelCacheGen::GenSaveOperatorCacheImpl(const std::string &tiling_data_type_name) {311+std::string OperatorLevelCacheGen::GenSaveOperatorCacheImpl() {
290 std::stringstream ss;312 std::stringstream ss;
291 ss << R"(313 ss << R"(
292 // 插入算子级缓存(带LRU老化)314 // 插入算子级缓存(带LRU老化)
293- static bool SaveOperatorCache(const std::array<uint32_t, kInputShapeSize>& shape_key,315+ static OperatorCacheSaveResult SaveOperatorCache(const std::array<uint32_t, kInputShapeSize>& shape_key,
294- const )"316+ const )"
295- << tiling_data_type_name317+ << "TilingData"
296 << R"(& tiling_data) {318 << R"(& tiling_data) {
297 auto& cache = GetOperatorCache();319 auto& cache = GetOperatorCache();
298 320 
299 // 1. 尝试直接插入321 // 1. 尝试直接插入
300 if (cache.Insert(shape_key, tiling_data)) {322 if (cache.Insert(shape_key, tiling_data)) {
301- OP_LOGI(OP_NAME, "[Operator Cache] SAVE SUCCESS: key=[%s]", )" +323+ return OperatorCacheSaveResult::kSaved;
302- GenShapeKeyToStringCode("shape_key") + R"();
303- return true;
304 }324 }
305- OP_LOGI(OP_NAME, "[Operator Cache] SAVE FAILED (cache full), key=[%s]", )" +
306- GenShapeKeyToStringCode("shape_key") + R"();
307 325 
308 // 2. 缓存满,执行LRU老化326 // 2. 缓存满,执行LRU老化
309- if (cache.Size() >= kOperatorCacheCapacity) {327+ if (cache.Size() >= kOperatorCacheCapacity * kLoadFactorThreshold) {
310- // 找到访问计数最小的条目
311- size_t min_index = 0;
312 uint64_t min_count = access_counts_[0];328 uint64_t min_count = access_counts_[0];
313 for (size_t i = 1; i < kOperatorCacheCapacity; ++i) {329 for (size_t i = 1; i < kOperatorCacheCapacity; ++i) {
314 if (access_counts_[i] < min_count) {330 if (access_counts_[i] < min_count) {
315- min_index = i;
316 min_count = access_counts_[i];331 min_count = access_counts_[i];
317 }332 }
318 }333 }
334+ last_aged_min_count_ = min_count;
319 335 
320- OP_LOGI(OP_NAME, "[Operator Cache] Clearing cache (LRU), min_count=%lu", min_count);336+ // 清空缓存后重新插入
321- // 淘汰最少使用的条目(简化处理:清空后重新插入)
322 cache.Clear();337 cache.Clear();
323 for (size_t i = 0; i < kOperatorCacheCapacity; ++i) {338 for (size_t i = 0; i < kOperatorCacheCapacity; ++i) {
324 access_counts_[i] = 0;339 access_counts_[i] = 0;
325 }340 }
326 341 
327 // 重新插入342 // 重新插入
328- return cache.Insert(shape_key, tiling_data);343+ return cache.Insert(shape_key, tiling_data) ? OperatorCacheSaveResult::kClearedAndSaved
344+ : OperatorCacheSaveResult::kFailed;
329 }345 }
330 346 
331- return false;347+ return OperatorCacheSaveResult::kFailed;
332 }348 }
333)";349)";
334 return ss.str();350 return ss.str();
335}351}
336 352 
337-std::string OperatorLevelCacheGen::GenContextCacheOperations(const std::string &tiling_data_type_name) {353+std::string OperatorLevelCacheGen::GenContextCacheOperations() {
338 std::stringstream ss;354 std::stringstream ss;
339- ss << GenFindOperatorCacheImpl(tiling_data_type_name);355+ ss << GenFindOperatorCacheImpl();
340 ss << "\n";356 ss << "\n";
341- ss << GenSaveOperatorCacheImpl(tiling_data_type_name);357+ ss << GenSaveOperatorCacheImpl();
342 return ss.str();358 return ss.str();
343}359}
344 360 
@@ -51,25 +51,16 @@ class OperatorLevelCacheGen : public TilingCacheCodeGen {
51 /**51 /**
52 * @brief 生成TilingCacheContext类定义52 * @brief 生成TilingCacheContext类定义
53 * @param code_printer 代码打印器53 * @param code_printer 代码打印器
54- * @param tiling_data_type_name TilingData类型名称
55 * @return af::Status54 * @return af::Status
56 */55 */
57- static af::Status GenTilingCacheContext(ge::CodePrinter &code_printer, const std::string &tiling_data_type_name);56+ static af::Status GenTilingCacheContext(ge::CodePrinter &code_printer);
58- 
59- /**
60- * @brief 生成TilingCacheContext静态成员定义(必须在cpp文件中)
61- * @param code_printer 代码打印器
62- * @return af::Status
63- */
64- static af::Status GenTilingCacheContextStaticDefs(ge::CodePrinter &code_printer);
65 57 
66 /**58 /**
67 * @brief 生成算子级缓存类型定义59 * @brief 生成算子级缓存类型定义
68 * @param code_printer 代码打印器60 * @param code_printer 代码打印器
69- * @param tiling_data_type_name TilingData类型名称
70 * @return af::Status61 * @return af::Status
71 */62 */
72- static af::Status GenOperatorCacheTypes(ge::CodePrinter &code_printer, const std::string &tiling_data_type_name);63+ static af::Status GenOperatorCacheTypes(ge::CodePrinter &code_printer);
73 /**64 /**
74 *65 *
75 * @param code_printer 代码打印器(函数体)66 * @param code_printer 代码打印器(函数体)
@@ -92,10 +83,9 @@ class OperatorLevelCacheGen : public TilingCacheCodeGen {
92 83 
93 /**84 /**
94 * @brief 生成Context类代码85 * @brief 生成Context类代码
95- * @param tiling_data_type_name TilingData类型名称
96 * @return af::Status86 * @return af::Status
97 */87 */
98- static std::string GenContextClass(const std::string &tiling_data_type_name);88+ static std::string GenContextClass();
99 89 
100 /**90 /**
101 * @brief 生成Context类结构体91 * @brief 生成Context类结构体
@@ -111,24 +101,21 @@ class OperatorLevelCacheGen : public TilingCacheCodeGen {
111 101 
112 /**102 /**
113 * @brief 生成Context类缓存操作方法103 * @brief 生成Context类缓存操作方法
114- * @param tiling_data_type_name TilingData类型名称
115 * @return af::Status104 * @return af::Status
116 */105 */
117- static std::string GenContextCacheOperations(const std::string &tiling_data_type_name);106+ static std::string GenContextCacheOperations();
118 107 
119 /**108 /**
120 * @brief 生成FindOperatorCache实现代码109 * @brief 生成FindOperatorCache实现代码
121- * @param tiling_data_type_name TilingData类型名称
122 * @return 生成的代码字符串110 * @return 生成的代码字符串
123 */111 */
124- static std::string GenFindOperatorCacheImpl(const std::string &tiling_data_type_name);112+ static std::string GenFindOperatorCacheImpl();
125 113 
126 /**114 /**
127 * @brief 生成SaveOperatorCache实现代码115 * @brief 生成SaveOperatorCache实现代码
128- * @param tiling_data_type_name TilingData类型名称
129 * @return 生成的代码字符串116 * @return 生成的代码字符串
130 */117 */
131- static std::string GenSaveOperatorCacheImpl(const std::string &tiling_data_type_name);118+ static std::string GenSaveOperatorCacheImpl();
132};119};
133} // namespace cache120} // namespace cache
134 121 
@@ -45,17 +45,19 @@ af::Status HighPerfTilingCodeGenImpl::GenSolverBaseClass() {
45 GE_ASSERT_TRUE(args_manager.Process(false), "Args manager process failed.");45 GE_ASSERT_TRUE(args_manager.Process(false), "Args manager process failed.");
46 total_models.emplace_back(args_manager);46 total_models.emplace_back(args_manager);
47 }47 }
48- std::string basic_solvers_head;48+ autofuse::GeneratedCode basic_solvers_head;
49 std::string basic_solvers_func;49 std::string basic_solvers_func;
50- basic_solvers_head = SolverPassManager::GenCommonBaseClassesHead(total_models);50+ basic_solvers_head = SolverPassManager::GenCommonBaseClassesHeader(total_models);
51 basic_solvers_func = SolverPassManager::GenCommonBaseClassesFunc(total_models);51 basic_solvers_func = SolverPassManager::GenCommonBaseClassesFunc(total_models);
52 std::regex pattern(std::string(kDefaultConfigMaxIterHeader) + std::string(kDefaultConfigMaxIterValue));52 std::regex pattern(std::string(kDefaultConfigMaxIterHeader) + std::string(kDefaultConfigMaxIterValue));
53 std::string result_head = std::regex_replace(53 std::string result_head = std::regex_replace(
54- basic_solvers_head, pattern,54+ basic_solvers_head.body, pattern,
55 kDefaultConfigMaxIterHeader + std::to_string(AutoFuseConfig::GetAttStrategyConfig().max_iter_num));55 kDefaultConfigMaxIterHeader + std::to_string(AutoFuseConfig::GetAttStrategyConfig().max_iter_num));
56 std::string result_func = std::regex_replace(56 std::string result_func = std::regex_replace(
57 basic_solvers_func, pattern,57 basic_solvers_func, pattern,
58 kDefaultConfigMaxIterHeader + std::to_string(AutoFuseConfig::GetAttStrategyConfig().max_iter_num));58 kDefaultConfigMaxIterHeader + std::to_string(AutoFuseConfig::GetAttStrategyConfig().max_iter_num));
59+ basic_solvers_head.body = result_head + "\n";
60+ autofuse::AppendGeneratedCode(atomic_headers_[autofuse::GeneratedHeaderId::kSolver], basic_solvers_head);
59 tiling_head_.AddLine(result_head);61 tiling_head_.AddLine(result_head);
60 tiling_func_.AddLine(result_func);62 tiling_func_.AddLine(result_func);
61 return af::SUCCESS;63 return af::SUCCESS;
@@ -593,7 +593,7 @@ inline AxesReorderSolver::DualAxesInfo AxesReorderSolver::InitializeDualAxesInfo
593 info.upper_bound_a = info.var_a->upper_bound(info.var_a->upper_bound_vars);593 info.upper_bound_a = info.var_a->upper_bound(info.var_a->upper_bound_vars);
594 info.upper_bound_b = info.var_b->upper_bound(info.var_b->upper_bound_vars);594 info.upper_bound_b = info.var_b->upper_bound(info.var_b->upper_bound_vars);
595 info.upper_bound_both = std::min(info.upper_bound_a, info.upper_bound_b);595 info.upper_bound_both = std::min(info.upper_bound_a, info.upper_bound_b);
596- info.low_bound_both = ::lcm(info.var_a->align, info.var_b->align);596+ info.low_bound_both = lcm(info.var_a->align, info.var_b->align);
597 OP_LOGD(OP_NAME, "[DFX] Axes: a(ub=%ld, align=%ld), b(ub=%ld, align=%ld), low_bound_both=%ld",597 OP_LOGD(OP_NAME, "[DFX] Axes: a(ub=%ld, align=%ld), b(ub=%ld, align=%ld), low_bound_both=%ld",
598 info.upper_bound_a, info.var_a->align, info.upper_bound_b, info.var_b->align, info.low_bound_both);598 info.upper_bound_a, info.var_a->align, info.upper_bound_b, info.var_b->align, info.low_bound_both);
599 return info;599 return info;
@@ -415,11 +415,18 @@ ExprExprMap SolverPassManager::GetOriginalInputAlign() const {
415}415}
416 416 
417std::string SolverPassManager::GenCommonBaseClassesHead(std::vector<ArgsManager> args_managers) {417std::string SolverPassManager::GenCommonBaseClassesHead(std::vector<ArgsManager> args_managers) {
418- std::string base_classes;418+ return GenCommonBaseClassesHeader(std::move(args_managers)).body;
419+}
420+ 
421+autofuse::GeneratedCode SolverPassManager::GenCommonBaseClassesHeader(std::vector<ArgsManager> args_managers) {
422+ autofuse::GeneratedCode base_classes;
419 for (uint32_t i = 0U; i < static_cast<std::uint32_t>(SolverType::ERROR); i++) {423 for (uint32_t i = 0U; i < static_cast<std::uint32_t>(SolverType::ERROR); i++) {
420 SolverType type = static_cast<SolverType>(i);424 SolverType type = static_cast<SolverType>(i);
421 if (IsNeedSolver(args_managers, type)) {425 if (IsNeedSolver(args_managers, type)) {
422- base_classes += GetSolverHead(type);426+ base_classes.body += GetSolverHead(type);
427+ if (type == SolverType::SEARCH_TILE) {
428+ autofuse::RequireSystemHeader(base_classes.dependencies, "cstddef");
429+ }
423 }430 }
424 }431 }
425 return base_classes;432 return base_classes;
@@ -12,6 +12,7 @@
12#include <string>12#include <string>
13#include <utility>13#include <utility>
14#include <algorithm>14#include <algorithm>
15+#include "common/tiling_source_dependencies.h"
15#include "base/base_types.h"16#include "base/base_types.h"
16#include "generator/preprocess/args_manager.h"17#include "generator/preprocess/args_manager.h"
17#include "generator/solver_pass/solver.h"18#include "generator/solver_pass/solver.h"
@@ -40,6 +41,7 @@ class SolverPassManager : public InputOutputSettersMixin<SolverPassManager>,
40 sub_case_tag_(case_id_info.sub_case_tag),41 sub_case_tag_(case_id_info.sub_case_tag),
41 tiling_data_type_(type_name) {}42 tiling_data_type_(type_name) {}
42 static std::string GenCommonBaseClassesHead(std::vector<ArgsManager> args_managers);43 static std::string GenCommonBaseClassesHead(std::vector<ArgsManager> args_managers);
44+ static autofuse::GeneratedCode GenCommonBaseClassesHeader(std::vector<ArgsManager> args_managers);
43 static std::string GenCommonBaseClassesFunc(std::vector<ArgsManager> args_managers);45 static std::string GenCommonBaseClassesFunc(std::vector<ArgsManager> args_managers);
44 std::string GenClassPass();46 std::string GenClassPass();
45 std::pair<std::string, std::string> GenFuncPass();47 std::pair<std::string, std::string> GenFuncPass();
@@ -69,9 +69,21 @@ af::Status IsUpperBoundValid(const Expr &min_expr, const Expr &max_expr) {
69 return af::SUCCESS;69 return af::SUCCESS;
70}70}
71 71 
72-void GenLogDefine(ge::CodePrinter &print) {72+void GenLogDefine(ge::CodePrinter &print, bool preserve_includes) {
73 const auto &slog_extend = AddSlogExtend();73 const auto &slog_extend = AddSlogExtend();
74- const auto &extend_define = slog_extend.empty() ? "\n" : slog_extend + "\n";74+ std::stringstream log_body;
75+ const std::set<std::string> known_includes = {
76+ "#include <cinttypes>", "#include <sys/syscall.h>", "#include <unistd.h>", "#include <cstdint>",
77+ "#include <stdio.h>", "#include <stdlib.h>", "#include <map>", "#include <securec.h>",
78+ "#include <vector>", "#include \"dlog_pub.h\"", "#include \"err_msg.h\""};
79+ std::istringstream log_stream(slog_extend);
80+ std::string line;
81+ while (std::getline(log_stream, line)) {
82+ if (known_includes.count(line) == 0U) {
83+ log_body << line << '\n';
84+ }
85+ }
86+ const auto extend_define = slog_extend.empty() ? "\n" : (preserve_includes ? slog_extend : log_body.str()) + "\n";
75 // 根据 ASCEND_GLOBAL_LOG_LEVEL 决定生成的宏内容:87 // 根据 ASCEND_GLOBAL_LOG_LEVEL 决定生成的宏内容:
76 // DLOG_NULL 时生成空宏,否则生成完整宏88 // DLOG_NULL 时生成空宏,否则生成完整宏
77 // 运行时通过 CheckLogLevel 动态判断是否真正输出89 // 运行时通过 CheckLogLevel 动态判断是否真正输出
@@ -394,6 +406,175 @@ std::string GenTilingScoreFuncDefineHead(bool is_uniq_group) {
394 return part1 + workspace_param + part2;406 return part1 + workspace_param + part2;
395}407}
396} // namespace408} // namespace
409+ 
410+namespace {
411+std::string GetAtomicHeaderKey(autofuse::GeneratedHeaderId header_id) {
412+ switch (header_id) {
413+ case autofuse::GeneratedHeaderId::kState:
414+ return kTilingStateHeaderIdentify;
415+ case autofuse::GeneratedHeaderId::kLog:
416+ return kTilingLogHeaderIdentify;
417+ case autofuse::GeneratedHeaderId::kPgo:
418+ return kTilingPgoHeaderIdentify;
419+ case autofuse::GeneratedHeaderId::kSolver:
420+ return kTilingSolverHeaderIdentify;
421+ case autofuse::GeneratedHeaderId::kApi:
422+ return kTilingApiHeaderIdentify;
423+ default:
424+ return "";
425+ }
426+}
427+ 
428+std::string GetAtomicHeaderGuard(autofuse::GeneratedHeaderId header_id) {
429+ switch (header_id) {
430+ case autofuse::GeneratedHeaderId::kState:
431+ return "__AUTOFUSE_TILING_FUNC_STATE_H__";
432+ case autofuse::GeneratedHeaderId::kLog:
433+ return "__AUTOFUSE_TILING_FUNC_LOG_H__";
434+ case autofuse::GeneratedHeaderId::kPgo:
435+ return "__AUTOFUSE_TILING_FUNC_PGO_H__";
436+ case autofuse::GeneratedHeaderId::kSolver:
437+ return "__AUTOFUSE_TILING_FUNC_SOLVER_H__";
438+ case autofuse::GeneratedHeaderId::kApi:
439+ return "__AUTOFUSE_TILING_FUNC_API_H__";
440+ default:
441+ return "";
442+ }
443+}
444+ 
445+std::string WrapAtomicHeaderBody(autofuse::GeneratedHeaderId header_id, const std::string &body,
446+ const std::string &tiling_data_type_name, bool is_autofuse) {
447+ const bool has_global_tiling_data = is_autofuse && tiling_data_type_name == "AutofuseTilingData";
448+ if (header_id == autofuse::GeneratedHeaderId::kLog) {
449+ return body;
450+ }
451+ if (header_id == autofuse::GeneratedHeaderId::kPgo) {
452+ if (has_global_tiling_data) {
453+ return "struct " + tiling_data_type_name + ";\nstruct AutofuseTilingDataPerf;\nnamespace optiling {\n" + body +
454+ "} // namespace optiling\n";
455+ }
456+ return "struct AutofuseTilingDataPerf;\nnamespace optiling {\nstruct " + tiling_data_type_name + ";\n" + body +
457+ "} // namespace optiling\n";
458+ }
459+ if (header_id == autofuse::GeneratedHeaderId::kApi) {
460+ if (has_global_tiling_data) {
461+ return "struct " + tiling_data_type_name + ";\nstruct AutofuseTilingDataPerf;\nuint32_t GetWorkspaceSize(const " +
462+ tiling_data_type_name +
463+ " &tiling_data);\nnamespace optiling {\nstruct PgoTensorArgs;\nstruct SearchConfig;\n" + body +
464+ "} // namespace optiling\n";
465+ }
466+ return "struct AutofuseTilingDataPerf;\nnamespace optiling {\nstruct " + tiling_data_type_name +
467+ ";\nstruct PgoTensorArgs;\nstruct SearchConfig;\n" + body + "} // namespace optiling\n";
468+ }
469+ std::string prefix;
470+ if (header_id == autofuse::GeneratedHeaderId::kSolver) {
471+ prefix = "using std::greater;\nusing std::string;\n";
472+ }
473+ return prefix + "namespace optiling {\n" + body + "} // namespace optiling\n";
474+}
475+} // namespace
476+ 
477+void TilingCodeGenImpl::AddAtomicHeaderLine(autofuse::GeneratedHeaderId header_id, const std::string &line) {
478+ AppendAtomicHeaderBody(header_id, line + "\n");
479+ tiling_head_.AddLine(line);
480+}
481+ 
482+void TilingCodeGenImpl::AppendAtomicHeaderBody(autofuse::GeneratedHeaderId header_id, const std::string &body) {
483+ atomic_headers_[header_id].body += body;
484+}
485+ 
486+void TilingCodeGenImpl::ResetTranslationUnit() {
487+ tiling_func_.Reset();
488+ translation_unit_ = {};
489+}
490+ 
491+void TilingCodeGenImpl::RequireTranslationUnitSystemHeader(const std::string &header) {
492+ autofuse::RequireSystemHeader(translation_unit_.dependencies, header);
493+}
494+ 
495+void TilingCodeGenImpl::RequireVarRelationSystemHeaders() {
496+ RequireTranslationUnitSystemHeader("cmath");
497+ RequireTranslationUnitSystemHeader("limits");
498+}
499+ 
500+void TilingCodeGenImpl::RequireTranslationUnitExternalHeader(const std::string &header) {
501+ autofuse::RequireExternalHeader(translation_unit_.dependencies, header);
502+}
503+ 
504+void TilingCodeGenImpl::RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId header_id) {
505+ autofuse::RequireGeneratedHeader(translation_unit_.dependencies, header_id);
506+}
507+ 
508+void TilingCodeGenImpl::RequireTranslationUnitTilingDataHeader() {
509+ if (config_.is_autofuse) {
510+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kTilingData);
511+ return;
512+ }
513+ RequireTranslationUnitExternalHeader(op_name_ + "_tiling_data.h");
514+}
515+ 
516+void TilingCodeGenImpl::AddApiTilingPreambles() {
517+ const std::string kSystemIncludePrefix = "#include <";
518+ const std::string kExternalIncludePrefix = "#include \"";
519+ std::set<std::string> api_tiling_preambles;
520+ for (const auto &model_info : tiling_model_info_) {
521+ for (const auto &node_param : model_info.node_name_to_api_code) {
522+ api_tiling_preambles.insert(node_param.second.head_files);
523+ }
524+ }
525+ for (const auto &preamble : api_tiling_preambles) {
526+ std::istringstream headers(preamble);
527+ std::string line;
528+ while (std::getline(headers, line)) {
529+ if (line.rfind(kSystemIncludePrefix, 0U) == 0U && line.back() == '>') {
530+ std::string header = line.substr(kSystemIncludePrefix.size());
531+ header.pop_back();
532+ RequireTranslationUnitSystemHeader(header);
533+ } else if (line.rfind(kExternalIncludePrefix, 0U) == 0U && line.back() == '"') {
534+ std::string header = line.substr(kExternalIncludePrefix.size());
535+ header.pop_back();
536+ RequireTranslationUnitExternalHeader(header);
537+ } else {
538+ tiling_func_.AddLine(line);
539+ }
540+ }
541+ }
542+}
543+ 
544+af::Status TilingCodeGenImpl::FinishTranslationUnit(const std::string &key,
545+ std::map<std::string, std::string> &tiling_res) {
546+ translation_unit_.body = tiling_func_.GetOutputStr();
547+ std::string output;
548+ GE_ASSERT_SUCCESS(autofuse::RenderTranslationUnit(translation_unit_, output));
549+ tiling_res[key] += output;
550+ return af::SUCCESS;
551+}
552+ 
553+af::Status TilingCodeGenImpl::FinishGeneratedHeaders(std::map<std::string, std::string> &tiling_res) {
554+ return FinishGeneratedHeaders(atomic_headers_, config_.tiling_data_type_name, config_.is_autofuse, tiling_res);
555+}
556+ 
557+af::Status TilingCodeGenImpl::FinishGeneratedHeaders(
558+ const std::map<autofuse::GeneratedHeaderId, autofuse::GeneratedCode> &generated_headers,
559+ const std::string &tiling_data_type_name, bool is_autofuse, std::map<std::string, std::string> &tiling_res) {
560+ const std::array<autofuse::GeneratedHeaderId, 5U> header_order = {
561+ autofuse::GeneratedHeaderId::kState, autofuse::GeneratedHeaderId::kLog, autofuse::GeneratedHeaderId::kPgo,
562+ autofuse::GeneratedHeaderId::kSolver, autofuse::GeneratedHeaderId::kApi};
563+ for (const auto header_id : header_order) {
564+ const auto iter = generated_headers.find(header_id);
565+ if (iter == generated_headers.end() ||
566+ (header_id == autofuse::GeneratedHeaderId::kPgo && iter->second.body.empty())) {
567+ continue;
568+ }
569+ autofuse::GeneratedCode header = iter->second;
570+ header.body = WrapAtomicHeaderBody(header_id, header.body, tiling_data_type_name, is_autofuse);
571+ std::string output;
572+ GE_ASSERT_SUCCESS(autofuse::RenderGeneratedHeader(header, GetAtomicHeaderGuard(header_id), output));
573+ tiling_res[GetAtomicHeaderKey(header_id)] = std::move(output);
574+ }
575+ return af::SUCCESS;
576+}
577+ 
397inline void SetTilingDefinition(const std::set<std::string> &var_names, const std::string &param_name,578inline void SetTilingDefinition(const std::set<std::string> &var_names, const std::string &param_name,
398 std::set<std::string> &tiling_data_vars,579 std::set<std::string> &tiling_data_vars,
399 std::map<std::string, std::string> &type_name_to_definition) {580 std::map<std::string, std::string> &type_name_to_definition) {
@@ -535,7 +716,14 @@ af::Status TilingCodeGenImpl::GetRelatedHardware(std::map<std::string, std::stri
535af::Status TilingCodeGenImpl::GenDurationCommonCode() {716af::Status TilingCodeGenImpl::GenDurationCommonCode() {
536 const auto duration_head_code = DurationGenHeadCode();717 const auto duration_head_code = DurationGenHeadCode();
537 if (!duration_head_code.empty()) {718 if (!duration_head_code.empty()) {
538- tiling_head_.AddLine(duration_head_code);719+ auto &log_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kLog].dependencies;
720+ for (const auto &header : {"cstdint", "memory", "string"}) {
721+ autofuse::RequireSystemHeader(log_dependencies, header);
722+ }
723+ for (const auto &header : {"chrono", "memory", "new", "string"}) {
724+ RequireTranslationUnitSystemHeader(header);
725+ }
726+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kLog, duration_head_code);
539 tiling_func_.AddLine(DurationGenDefineCode());727 tiling_func_.AddLine(DurationGenDefineCode());
540 }728 }
541 return af::SUCCESS;729 return af::SUCCESS;
@@ -695,12 +883,7 @@ af::Status TilingCodeGenImpl::GetReuseVarNames(std::map<std::string, std::string
695 return af::SUCCESS;883 return af::SUCCESS;
696}884}
697 885 
698-af::Status TilingCodeGenImpl::GenStructCopyDef() {886+af::Status TilingCodeGenImpl::CollectStructCopyVars(std::set<std::string> &tiling_data_vars) {
699- std::set<std::string> tiling_data_vars;
700- // 获取所有的var name和复用var的映射关系
701- std::map<std::string, std::string> var_names_to_reuse_var_name;
702- std::set<ReuseScheduleGroupPtr> reuse_schedule_groups;
703- GE_ASSERT_SUCCESS(GetReuseVarNames(var_names_to_reuse_var_name));
704 for (const auto &model_info : tiling_model_info_) {887 for (const auto &model_info : tiling_model_info_) {
705 ArgsManager args_manager(model_info);888 ArgsManager args_manager(model_info);
706 GE_ASSERT_TRUE(args_manager.Process(false), "Args manager process failed.");889 GE_ASSERT_TRUE(args_manager.Process(false), "Args manager process failed.");
@@ -727,25 +910,36 @@ af::Status TilingCodeGenImpl::GenStructCopyDef() {
727 }910 }
728 }911 }
729 }912 }
913+ return af::SUCCESS;
914+}
915+ 
916+af::Status TilingCodeGenImpl::GenStructCopyDef() {
917+ std::set<std::string> tiling_data_vars;
918+ // 获取所有的var name和复用var的映射关系
919+ std::map<std::string, std::string> var_names_to_reuse_var_name;
920+ GE_ASSERT_SUCCESS(GetReuseVarNames(var_names_to_reuse_var_name));
921+ GE_ASSERT_SUCCESS(CollectStructCopyVars(tiling_data_vars));
730 tiling_data_vars.insert("tiling_key");922 tiling_data_vars.insert("tiling_key");
731 tiling_data_vars.insert(BaseTypeUtils::DumpHardware(HardwareDef::CORENUM));923 tiling_data_vars.insert(BaseTypeUtils::DumpHardware(HardwareDef::CORENUM));
732 if (config_.gen_extra_infos) {924 if (config_.gen_extra_infos) {
733 tiling_data_vars.insert("workspaceSize");925 tiling_data_vars.insert("workspaceSize");
734 }926 }
735- tiling_head_.AddLine("struct TilingDataCopy {");927+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState, "struct TilingDataCopy {");
736 for (const auto &var : tiling_data_vars) {928 for (const auto &var : tiling_data_vars) {
737 // 如果没有复用,则定义该变量929 // 如果没有复用,则定义该变量
738 std::string reuse_var = var;930 std::string reuse_var = var;
739 const auto &iter = var_names_to_reuse_var_name.find(var);931 const auto &iter = var_names_to_reuse_var_name.find(var);
740 if (iter == var_names_to_reuse_var_name.end()) {932 if (iter == var_names_to_reuse_var_name.end()) {
741- tiling_head_.AddLine(" uint32_t " + var + ";");933+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState, " uint32_t " + var + ";");
742 } else {934 } else {
743 reuse_var = iter->second;935 reuse_var = iter->second;
744 }936 }
745- tiling_head_.AddLine(" void set_" + var + "(uint32_t val) { " + reuse_var + " = val; }");937+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState,
746- tiling_head_.AddLine(" inline uint32_t get_" + var + "() { return " + reuse_var + "; }");938+ " void set_" + var + "(uint32_t val) { " + reuse_var + " = val; }");
939+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState,
940+ " inline uint32_t get_" + var + "() { return " + reuse_var + "; }");
747 }941 }
748- tiling_head_.AddLine("};");942+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState, "};");
749 return af::SUCCESS;943 return af::SUCCESS;
750}944}
751 945 
@@ -772,70 +966,113 @@ af::Status TilingCodeGenImpl::GenCacheHashMapDef() {
772 return af::SUCCESS;966 return af::SUCCESS;
773 }967 }
774 968 
775- size_t input_vars_size = CollectInputVarsSize();969+ auto &state_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kState].dependencies;
970+ for (const auto &header : {"array", "cstddef", "cstdint", "memory"}) {
971+ autofuse::RequireSystemHeader(state_dependencies, header);
972+ }
973+ 
974+ const size_t input_vars_size = CollectInputVarsSize();
975+ ge::CodePrinter state_header;
776 976 
777 // 生成常量定义(Operator和Group缓存共享)977 // 生成常量定义(Operator和Group缓存共享)
778- cache::OperatorLevelCacheGen::GenConstantDefs(tiling_head_, input_vars_size);978+ cache::OperatorLevelCacheGen::GenConstantDefs(state_header, input_vars_size);
779 979 
780 // 生成FixedSizeHashMap模板定义(Operator和Group缓存共享)980 // 生成FixedSizeHashMap模板定义(Operator和Group缓存共享)
781- GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenFixedSizeHashMapDef(tiling_head_),981+ GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenFixedSizeHashMapDef(state_header),
782 "Generate FixedSizeHashMap definition failed.");982 "Generate FixedSizeHashMap definition failed.");
783 983 
784 // 只在Operator缓存开启时生成OperatorCache相关类型和类984 // 只在Operator缓存开启时生成OperatorCache相关类型和类
785 if (config_.cache_enabled_at_compile_time) {985 if (config_.cache_enabled_at_compile_time) {
786- GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenOperatorCacheTypes(tiling_head_, config_.tiling_data_type_name),986+ GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenOperatorCacheTypes(state_header),
787 "Generate Operator cache types failed.");987 "Generate Operator cache types failed.");
788 988 
789- GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenTilingCacheContext(tiling_head_, config_.tiling_data_type_name),989+ GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenTilingCacheContext(state_header),
790 "Generate TilingCacheContext failed.");990 "Generate TilingCacheContext failed.");
791 }991 }
792 992 
993+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, state_header.GetOutputStr());
994+ tiling_head_.AddLine(state_header.GetOutputStr());
995+ 
793 return af::SUCCESS;996 return af::SUCCESS;
794}997}
795 998 
999+void TilingCodeGenImpl::GenPgoCallbackDefs(ge::CodePrinter &pgo_header) {
1000+ pgo_header.AddLine("#ifndef AUTOFUSE_PGO_TENSOR_ARGS_DEFINED");
1001+ pgo_header.AddLine("#define AUTOFUSE_PGO_TENSOR_ARGS_DEFINED");
1002+ pgo_header.AddLine("struct PgoTensorArgs {");
1003+ pgo_header.AddLine(" void **inputs = nullptr;");
1004+ pgo_header.AddLine(" uint32_t input_num = 0;");
1005+ pgo_header.AddLine(" void **outputs = nullptr;");
1006+ pgo_header.AddLine(" uint32_t output_num = 0;");
1007+ pgo_header.AddLine("};");
1008+ pgo_header.AddLine("#endif");
1009+ pgo_header.AddLine("typedef long int (*ProfilingCallback)(" + GenPgoTensorArgsDef());
1010+ pgo_header.AddLine("void* stream, uint32_t workspaceSize, " + config_.tiling_data_type_name +
1011+ "* tiling_data, double* cost_time);");
1012+ pgo_header.AddLine("typedef long int (*ProfilingBatchCallback)(" + GenPgoTensorArgsDef());
1013+ pgo_header.AddLine("void* stream, uint32_t workspaceSize, std::vector<AutofuseTilingDataPerf> *profiles);");
1014+}
1015+ 
1016+void TilingCodeGenImpl::GenPgoConfigDefs(ge::CodePrinter &pgo_header) {
1017+ pgo_header.AddLine("#ifndef AUTOFUSE_PGO_CONFIG_DEFINED");
1018+ pgo_header.AddLine("#define AUTOFUSE_PGO_CONFIG_DEFINED");
1019+ pgo_header.AddLine("class PgoConfig {");
1020+ pgo_header.AddLine("public:");
1021+ pgo_header.AddLine(" static PgoConfig& Instance() {");
1022+ pgo_header.AddLine(" static PgoConfig instance;");
1023+ pgo_header.AddLine(" return instance;");
1024+ pgo_header.AddLine(" }");
1025+ pgo_header.AddLine(" void ResetRuntimeOverrides() {");
1026+ pgo_header.AddLine(" need_change_solver_run = false;");
1027+ pgo_header.AddLine(" pgo_threshold_index = 0;");
1028+ pgo_header.AddLine(" pgo_ub_threshold_list = {0.2, 0.1, 0, 0.05, 0.1};");
1029+ pgo_header.AddLine(" pgo_corenum_threshold_list = {0.4, 0.4, 1, 1, 0.8};");
1030+ pgo_header.AddLine(" }");
1031+ pgo_header.AddLine(" ProfilingCallback single_callback;");
1032+ pgo_header.AddLine(" ProfilingBatchCallback batch_callback;");
1033+ pgo_header.AddLine(" PgoTensorArgs *tensor_args = nullptr;");
1034+ pgo_header.AddLine(" int32_t pgo_algorithm = 1; // 0 for pruning, 1 for core num");
1035+ pgo_header.AddLine(" bool need_change_solver_run = false;");
1036+ pgo_header.AddLine(" size_t pgo_threshold_index = 0;");
1037+ pgo_header.AddLine(" constexpr static size_t pgo_threshold_list_size = 5;");
1038+ pgo_header.AddLine(" std::array<double, pgo_threshold_list_size> pgo_ub_threshold_list{0.2, 0.1, 0, 0.05, 0.1};");
1039+ pgo_header.AddLine(" std::array<double, pgo_threshold_list_size> pgo_corenum_threshold_list{0.4, 0.4, 1, 1, 0.8};");
1040+ pgo_header.AddLine("private:");
1041+ pgo_header.AddLine(" PgoConfig() = default;");
1042+ pgo_header.AddLine(" ~PgoConfig() = default;");
1043+ pgo_header.AddLine(" PgoConfig(const PgoConfig &) = delete;");
1044+ pgo_header.AddLine(" PgoConfig &operator=(const PgoConfig &) = delete;");
1045+ pgo_header.AddLine("};");
1046+ pgo_header.AddLine("class PgoConfigRuntimeGuard {");
1047+ pgo_header.AddLine("public:");
1048+ pgo_header.AddLine(" PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }");
1049+ pgo_header.AddLine(" ~PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }");
1050+ pgo_header.AddLine("};");
1051+ pgo_header.AddLine("#endif");
1052+}
1053+ 
796void TilingCodeGenImpl::GenPgoHeaderCodesTail() {1054void TilingCodeGenImpl::GenPgoHeaderCodesTail() {
797- tiling_data_.AddLine("using AutofuseTilingData = " + config_.tiling_data_type_name + ";\n");1055+ if (!config_.is_autofuse) {
798- std::string pgo_perf_struct = {1056+ tiling_data_.AddLine("using AutofuseTilingData = " + config_.tiling_data_type_name + ";\n");
799- "struct AutofuseTilingDataPerf {\n"1057+ const std::string pgo_perf_struct = {
800- " AutofuseTilingData tiling_data;\n"1058+ "struct AutofuseTilingDataPerf {\n"
801- " double best_perf;\n"1059+ " AutofuseTilingData tiling_data;\n"
802- "};\n"};1060+ " double best_perf;\n"
803- tiling_data_.AddLine(pgo_perf_struct);1061+ "};\n"};
804- tiling_data_.AddLine("#ifndef AUTOFUSE_PGO_TENSOR_ARGS_DEFINED");1062+ tiling_data_.AddLine(pgo_perf_struct);
805- tiling_data_.AddLine("#define AUTOFUSE_PGO_TENSOR_ARGS_DEFINED");1063+ }
806- tiling_data_.AddLine("struct PgoTensorArgs {");1064+ ge::CodePrinter pgo_header;
807- tiling_data_.AddLine(" void **inputs = nullptr;");1065+ GenPgoCallbackDefs(pgo_header);
808- tiling_data_.AddLine(" uint32_t input_num = 0;");1066+ GenPgoConfigDefs(pgo_header);
809- tiling_data_.AddLine(" void **outputs = nullptr;");1067+ const std::string pgo_header_body = pgo_header.GetOutputStr();
810- tiling_data_.AddLine(" uint32_t output_num = 0;");1068+ if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
811- tiling_data_.AddLine("};");1069+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kPgo, pgo_header_body);
812- tiling_data_.AddLine("#endif");1070+ }
813- tiling_data_.AddLine("typedef long int (*ProfilingCallback)(" + GenPgoTensorArgsDef());1071+ tiling_head_.AddLine(WrapAtomicHeaderBody(autofuse::GeneratedHeaderId::kPgo, pgo_header_body,
814- tiling_data_.AddLine("void* stream, uint32_t workspaceSize, AutofuseTilingData* tiling_data, double* cost_time);");1072+ config_.tiling_data_type_name, config_.is_autofuse));
815- tiling_data_.AddLine("typedef long int (*ProfilingBatchCallback)(" + GenPgoTensorArgsDef());1073+ if (!config_.is_autofuse) {
816- tiling_data_.AddLine("void* stream, uint32_t workspaceSize, std::vector<AutofuseTilingDataPerf> *profiles);");1074+ tiling_data_.AddLine(pgo_header_body);
817- tiling_data_.AddLine("class PgoConfig {");1075+ }
818- tiling_data_.AddLine("public:");
819- tiling_data_.AddLine(" static PgoConfig& Instance() {");
820- tiling_data_.AddLine(" static PgoConfig instance;");
821- tiling_data_.AddLine(" return instance;");
822- tiling_data_.AddLine(" }");
823- tiling_data_.AddLine(" ProfilingCallback single_callback;");
824- tiling_data_.AddLine(" ProfilingBatchCallback batch_callback;");
825- tiling_data_.AddLine(" PgoTensorArgs *tensor_args = nullptr;");
826- tiling_data_.AddLine(" int32_t pgo_algorithm = 1; // 0 for pruning, 1 for core num");
827- tiling_data_.AddLine(" bool need_change_solver_run = false;");
828- tiling_data_.AddLine(" size_t pgo_threshold_index = 0;");
829- tiling_data_.AddLine(" constexpr static size_t pgo_threshold_list_size = 5;");
830- tiling_data_.AddLine(" std::array<double, pgo_threshold_list_size> pgo_ub_threshold_list{0.2, 0.1, 0, 0.05, 0.1};");
831- tiling_data_.AddLine(
832- " std::array<double, pgo_threshold_list_size> pgo_corenum_threshold_list{0.4, 0.4, 1, 1, 0.8};");
833- tiling_data_.AddLine("private:");
834- tiling_data_.AddLine(" PgoConfig() = default;");
835- tiling_data_.AddLine(" ~PgoConfig() = default;");
836- tiling_data_.AddLine(" PgoConfig(const PgoConfig &) = delete;");
837- tiling_data_.AddLine(" PgoConfig &operator=(const PgoConfig &) = delete;");
838- tiling_data_.AddLine("};");
839}1076}
840 1077 
841af::Status TilingCodeGenImpl::GenHeaderInclude() {1078af::Status TilingCodeGenImpl::GenHeaderInclude() {
@@ -1139,7 +1376,7 @@ enum class PipeType : uint8_t {
1139 ALL,1376 ALL,
1140};1377};
1141)";1378)";
1142- tiling_head_.AddLine(kPipeType);1379+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState, kPipeType);
1143 return af::SUCCESS;1380 return af::SUCCESS;
1144}1381}
1145 1382 
@@ -1430,20 +1667,23 @@ af::Status TilingCodeGenImpl::GenExternFuncDef() {
1430}1667}
1431 1668 
1432af::Status TilingCodeGenImpl::GenExpressionMacro() {1669af::Status TilingCodeGenImpl::GenExpressionMacro() {
1433- tiling_head_.AddLine("#define Max(a, b) ((double)(a) > (double)(b) ? (a) : (b))");1670+ const std::array<std::string, 14U> macros = {"#define Max(a, b) ((double)(a) > (double)(b) ? (a) : (b))",
1434- tiling_head_.AddLine("#define Min(a, b) ((double)(a) < (double)(b) ? (a) : (b))");1671+ "#define Min(a, b) ((double)(a) < (double)(b) ? (a) : (b))",
1435- tiling_head_.AddLine("#define Abs(a) ((double)(a) >= 0 ? (a) : -(a))");1672+ "#define Abs(a) ((double)(a) >= 0 ? (a) : -(a))",
1436- tiling_head_.AddLine("#define Log(a) (log((double)(a)))");1673+ "#define Log(a) (log((double)(a)))",
1437- tiling_head_.AddLine("#define Pow(a, b) pow(a, b)");1674+ "#define Pow(a, b) pow(a, b)",
1438- tiling_head_.AddLine("#define Rational(a, b) ((double)(a) / (double)(b))");1675+ "#define Rational(a, b) ((double)(a) / (double)(b))",
1439- tiling_head_.AddLine("#define ExpectEq(a, b) ((a) == (b))");1676+ "#define ExpectEq(a, b) ((a) == (b))",
1440- tiling_head_.AddLine("#define ExpectNe(a, b) ((a) != (b))");1677+ "#define ExpectNe(a, b) ((a) != (b))",
1441- tiling_head_.AddLine("#define ExpectLe(a, b) ((a) <= (b))");1678+ "#define ExpectLe(a, b) ((a) <= (b))",
1442- tiling_head_.AddLine("#define ExpectLt(a, b) ((a) < (b))");1679+ "#define ExpectLt(a, b) ((a) < (b))",
1443- tiling_head_.AddLine("#define LogicAnd(a, b) ((a) && (b))");1680+ "#define LogicAnd(a, b) ((a) && (b))",
1444- tiling_head_.AddLine("#define LogicOr(a, b) ((a) || (b))");1681+ "#define LogicOr(a, b) ((a) || (b))",
1445- tiling_head_.AddLine("#define True true");1682+ "#define True true",
1446- tiling_head_.AddLine("#define False false");1683+ "#define False false"};
1684+ for (const auto &macro : macros) {
1685+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kSolver, macro);
1686+ }
1447 return af::SUCCESS;1687 return af::SUCCESS;
1448}1688}
1449 1689 
@@ -1475,59 +1715,69 @@ af::Status TilingCodeGenImpl::GenMacroInclude() {
1475 for (const auto &head_file : uniq_head_files) {1715 for (const auto &head_file : uniq_head_files) {
1476 tiling_head_.AddLine(head_file);1716 tiling_head_.AddLine(head_file);
1477 }1717 }
1478- GenLogDefine(tiling_head_);1718+ GenLogDefine(tiling_head_, true);
1719+ ge::CodePrinter log_header;
1720+ GenLogDefine(log_header, false);
1721+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kLog, log_header.GetOutputStr());
1479 if (config_.gen_tiling_data) {1722 if (config_.gen_tiling_data) {
1480 // 如果是自己生成的tilingdata定义,需要在实现里面include 该头文件1723 // 如果是自己生成的tilingdata定义,需要在实现里面include 该头文件
1481 tiling_head_.AddLine("#include \"" + op_name_ + "_tiling_data.h\"");1724 tiling_head_.AddLine("#include \"" + op_name_ + "_tiling_data.h\"");
1482 }1725 }
1483 GenExpressionMacro();1726 GenExpressionMacro();
1484- tiling_head_.AddLine("#define MAX_SOLUTION 50");1727+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kSolver, "#define MAX_SOLUTION 50");
1485- tiling_head_.AddLine("#define OP_NAME \"" + op_name_ + "\"");1728+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kLog, "#define OP_NAME \"" + op_name_ + "\"");
1486 tiling_head_.AddLine("");1729 tiling_head_.AddLine("");
1487 GE_ASSERT_SUCCESS(GenDurationCommonCode(), "Generate duration common code failed.");1730 GE_ASSERT_SUCCESS(GenDurationCommonCode(), "Generate duration common code failed.");
1488 return af::SUCCESS;1731 return af::SUCCESS;
1489}1732}
1490 1733 
1491af::Status TilingCodeGenImpl::GenToolFuncs() {1734af::Status TilingCodeGenImpl::GenToolFuncs() {
1492- tiling_head_.AddLine("inline bool IsEqual(double a, double b)");1735+ auto &solver_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kSolver].dependencies;
1493- tiling_head_.AddLine("{");1736+ for (const auto &header : {"cmath", "cstdint", "type_traits"}) {
1494- tiling_head_.AddLine(" const double epsilon = 1e-8;");1737+ autofuse::RequireSystemHeader(solver_dependencies, header);
1495- tiling_head_.AddLine(" double abs = (a > b) ? (a - b) : (b - a);");1738+ }
1496- tiling_head_.AddLine(" return abs < epsilon;");1739+ ge::CodePrinter solver_header;
1497- tiling_head_.AddLine("}");1740+ solver_header.AddLine("inline bool IsEqual(double a, double b)");
1498- tiling_head_.AddLine("template<typename T1, typename T2>");1741+ solver_header.AddLine("{");
1499- tiling_head_.AddLine("inline double TernaryOp(bool cond, T1 a, T2 b)");1742+ solver_header.AddLine(" const double epsilon = 1e-8;");
1500- tiling_head_.AddLine("{");1743+ solver_header.AddLine(" double abs = (a > b) ? (a - b) : (b - a);");
1501- tiling_head_.AddLine(" return static_cast<double>(cond ? a : b);");1744+ solver_header.AddLine(" return abs < epsilon;");
1502- tiling_head_.AddLine("}");1745+ solver_header.AddLine("}");
1503- tiling_head_.AddLine("template<typename T>");1746+ solver_header.AddLine("template<typename T1, typename T2>");
1504- tiling_head_.AddLine("inline T Ceiling(T a)");1747+ solver_header.AddLine("inline double TernaryOp(bool cond, T1 a, T2 b)");
1505- tiling_head_.AddLine("{");1748+ solver_header.AddLine("{");
1506- tiling_head_.AddLine(" T value = static_cast<T>(static_cast<int64_t>(a));");1749+ solver_header.AddLine(" return static_cast<double>(cond ? a : b);");
1507- tiling_head_.AddLine(" return (IsEqual(value, a)) ? value : (value + 1);");1750+ solver_header.AddLine("}");
1508- tiling_head_.AddLine("}");1751+ solver_header.AddLine("template<typename T>");
1509- tiling_head_.AddLine("template<typename T>");1752+ solver_header.AddLine("inline T Ceiling(T a)");
1510- tiling_head_.AddLine("inline T Floor(T a)");1753+ solver_header.AddLine("{");
1511- tiling_head_.AddLine("{");1754+ solver_header.AddLine(" T value = static_cast<T>(static_cast<int64_t>(a));");
1512- tiling_head_.AddLine(" return static_cast<T>(static_cast<int64_t>(a));");1755+ solver_header.AddLine(" return (IsEqual(value, a)) ? value : (value + 1);");
1513- tiling_head_.AddLine("}");1756+ solver_header.AddLine("}");
1514- tiling_head_.AddLine("template<typename T1, typename T2>");1757+ solver_header.AddLine("template<typename T>");
1515- tiling_head_.AddLine("inline auto Mod(T1 a, T2 b)->decltype(a % b)");1758+ solver_header.AddLine("inline T Floor(T a)");
1516- tiling_head_.AddLine("{");1759+ solver_header.AddLine("{");
1517- tiling_head_.AddLine(" return a % b;");1760+ solver_header.AddLine(" return static_cast<T>(static_cast<int64_t>(a));");
1518- tiling_head_.AddLine("}");1761+ solver_header.AddLine("}");
1519- tiling_head_.AddLine("template<typename T1, typename T2>");1762+ solver_header.AddLine("template<typename T1, typename T2>");
1520- tiling_head_.AddLine(1763+ solver_header.AddLine("inline auto Mod(T1 a, T2 b)->decltype(a % b)");
1764+ solver_header.AddLine("{");
1765+ solver_header.AddLine(" return a % b;");
1766+ solver_header.AddLine("}");
1767+ solver_header.AddLine("template<typename T1, typename T2>");
1768+ solver_header.AddLine(
1521 "inline auto Mod(T1 a, T2 b)->typename std::enable_if<std::is_floating_point<T1>::value || "1769 "inline auto Mod(T1 a, T2 b)->typename std::enable_if<std::is_floating_point<T1>::value || "
1522 "std::is_floating_point<T2>::value, decltype(std::fmod(a, b))>::type");1770 "std::is_floating_point<T2>::value, decltype(std::fmod(a, b))>::type");
1523- tiling_head_.AddLine("{");1771+ solver_header.AddLine("{");
1524- tiling_head_.AddLine(" return std::fmod(a, b);");1772+ solver_header.AddLine(" return std::fmod(a, b);");
1525- tiling_head_.AddLine("}");1773+ solver_header.AddLine("}");
1526- tiling_head_.AddLine("template<typename TI, typename TO>");1774+ solver_header.AddLine("template<typename TI, typename TO>");
1527- tiling_head_.AddLine("inline TO &RefToRef(TI &ptr) {");1775+ solver_header.AddLine("inline TO &RefToRef(TI &ptr) {");
1528- tiling_head_.AddLine(" return *(reinterpret_cast<TO *>(reinterpret_cast<void *>(&ptr)));");1776+ solver_header.AddLine(" return *(reinterpret_cast<TO *>(reinterpret_cast<void *>(&ptr)));");
1529- tiling_head_.AddLine("}");1777+ solver_header.AddLine("}");
1530- tiling_head_.AddLine("");1778+ solver_header.AddLine("");
1779+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kSolver, solver_header.GetOutputStr());
1780+ tiling_head_.AddLine(solver_header.GetOutputStr());
1531 return af::SUCCESS;1781 return af::SUCCESS;
1532}1782}
1533 1783 
@@ -2055,15 +2305,22 @@ af::Status TilingCodeGenImpl::GenGetTilingDataFromCopy() {
2055}2305}
2056 2306 
2057af::Status TilingCodeGenImpl::GenFindCacheAndSaveCache() {2307af::Status TilingCodeGenImpl::GenFindCacheAndSaveCache() {
2308+ ge::CodePrinter state_header;
2309+ auto &state_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kState].dependencies;
2310+ for (const auto &header : {"array", "cstddef", "cstdint"}) {
2311+ autofuse::RequireSystemHeader(state_dependencies, header);
2312+ }
2058 // 当OperatorCache关闭但GroupCache开启时,需要在这里补齐GroupCache依赖的共享定义2313 // 当OperatorCache关闭但GroupCache开启时,需要在这里补齐GroupCache依赖的共享定义
2059 if (!config_.cache_enabled_at_compile_time) {2314 if (!config_.cache_enabled_at_compile_time) {
2060- cache::OperatorLevelCacheGen::GenConstantDefs(tiling_head_, CollectInputVarsSize());2315+ cache::OperatorLevelCacheGen::GenConstantDefs(state_header, CollectInputVarsSize());
2061- GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenFixedSizeHashMapDef(tiling_head_),2316+ GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenFixedSizeHashMapDef(state_header),
2062 "Generate FixedSizeHashMap definition for Group cache failed.");2317 "Generate FixedSizeHashMap definition for Group cache failed.");
2063 }2318 }
2064 2319 
2065- GE_ASSERT_SUCCESS(group_level_cache_gen_->GenGroupCacheTypes(tiling_head_, cache_capacity_),2320+ GE_ASSERT_SUCCESS(group_level_cache_gen_->GenGroupCacheTypes(state_header, cache_capacity_),
2066 "Generate Group cache types failed.");2321 "Generate Group cache types failed.");
2322+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, state_header.GetOutputStr());
2323+ tiling_head_.AddLine(state_header.GetOutputStr());
2067 2324 
2068 GE_ASSERT_SUCCESS(group_level_cache_gen_->GenGroupCacheFunctions(tiling_func_, config_.tiling_data_type_name),2325 GE_ASSERT_SUCCESS(group_level_cache_gen_->GenGroupCacheFunctions(tiling_func_, config_.tiling_data_type_name),
2069 "Generate Group cache functions failed.");2326 "Generate Group cache functions failed.");
@@ -2616,11 +2873,14 @@ af::Status TilingCodeGenImpl::GenGetTilingKey() {
2616af::Status TilingCodeGenImpl::GenPGOSearchTilingKey() {2873af::Status TilingCodeGenImpl::GenPGOSearchTilingKey() {
2617 GE_ASSERT_SUCCESS(GenSearchAllTilingbyCaseId(), "Gen SearchAllTilingbyCaseId failed.");2874 GE_ASSERT_SUCCESS(GenSearchAllTilingbyCaseId(), "Gen SearchAllTilingbyCaseId failed.");
2618 std::string params = config_.tiling_data_type_name + " &tiling_data" + ", int32_t tiling_case_id";2875 std::string params = config_.tiling_data_type_name + " &tiling_data" + ", int32_t tiling_case_id";
2619- tiling_head_.AddLine(2876+ const std::string output_tiling_data_type =
2620- "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params +2877+ config_.is_autofuse ? "AutofuseTilingData" : config_.tiling_data_type_name;
2621- ", AutofuseTilingData* output_tiling_data," + GenPgoTensorArgsDef() +2878+ AddAtomicHeaderLine(
2622- "void* stream, uint32_t workspaceSize, double& out_best_perf, std::unordered_map<int64_t, uint64_t> "2879+ autofuse::GeneratedHeaderId::kApi,
2623- "&workspace_map, std::vector<uint32_t*> block_dim_vec={}, const SearchConfig *search_cfg=nullptr);");2880+ "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params + ", " +
2881+ output_tiling_data_type + "* output_tiling_data," + GenPgoTensorArgsDef() +
2882+ "void* stream, uint32_t workspaceSize, double& out_best_perf, std::unordered_map<int64_t, uint64_t> "
2883+ "&workspace_map, std::vector<uint32_t*> block_dim_vec={}, const SearchConfig *search_cfg=nullptr);");
2624 tiling_func_.AddLine(2884 tiling_func_.AddLine(
2625 "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params +2885 "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params +
2626 ", AutofuseTilingData* output_tiling_data," + GenPgoTensorArgsDef() +2886 ", AutofuseTilingData* output_tiling_data," + GenPgoTensorArgsDef() +
@@ -2784,13 +3044,63 @@ af::Status TilingCodeGenImpl::GenHeaderCodesSummaryBody() {
2784void TilingCodeGenImpl::GenTilingHeadMultiGroup() {3044void TilingCodeGenImpl::GenTilingHeadMultiGroup() {
2785 std::string params = config_.tiling_data_type_name + " &tiling_data, int32_t tiling_case_id";3045 std::string params = config_.tiling_data_type_name + " &tiling_data, int32_t tiling_case_id";
2786 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {3046 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
2787- tiling_head_.AddLine(3047+ AddAtomicHeaderLine(
2788- "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params +3048+ autofuse::GeneratedHeaderId::kApi,
2789- ", AutofuseTilingData* output_tiling_data," + GenPgoTensorArgsDef() +3049+ "bool PGOSearchTilingKey(std::vector<AutofuseTilingDataPerf>& tiling_data_list, " + params + ", " +
2790- "void* stream, uint32_t workspaceSize, double& best_perf, const SearchConfig *search_cfg=nullptr);");3050+ config_.tiling_data_type_name + "* output_tiling_data," + GenPgoTensorArgsDef() +
3051+ "void* stream, uint32_t workspaceSize, double& best_perf, const SearchConfig *search_cfg=nullptr);");
2791 }3052 }
2792}3053}
2793 3054 
3055+void TilingCodeGenImpl::InitTilingHeadCodeGeneration() {
3056+ tiling_head_.Reset();
3057+ ResetTranslationUnit();
3058+ tiling_data_.Reset();
3059+ atomic_headers_.clear();
3060+ auto &state_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kState].dependencies;
3061+ autofuse::RequireSystemHeader(state_dependencies, "cstdint");
3062+ auto &solver_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kSolver].dependencies;
3063+ for (const auto &header : {"functional", "string"}) {
3064+ autofuse::RequireSystemHeader(solver_dependencies, header);
3065+ }
3066+ auto &api_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kApi].dependencies;
3067+ autofuse::RequireSystemHeader(api_dependencies, "cstdint");
3068+ if (!is_uniq_group_ || config_.enable_autofuse_pgo || config_.is_inductor_scene) {
3069+ autofuse::RequireSystemHeader(api_dependencies, "unordered_map");
3070+ }
3071+ if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
3072+ autofuse::RequireSystemHeader(api_dependencies, "vector");
3073+ }
3074+ auto &log_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kLog].dependencies;
3075+ if (!AddSlogExtend().empty()) {
3076+ for (const auto &header : {"cinttypes", "cstdarg", "cstdint", "cstring", "securec.h", "stdlib.h", "sys/syscall.h",
3077+ "unistd.h", "vector"}) {
3078+ autofuse::RequireSystemHeader(log_dependencies, header);
3079+ }
3080+ autofuse::RequireExternalHeader(log_dependencies, "dlog_pub.h");
3081+ autofuse::RequireExternalHeader(log_dependencies, "err_msg.h");
3082+ }
3083+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kLog);
3084+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kSolver);
3085+}
3086+ 
3087+void TilingCodeGenImpl::GenPgoSearchConfigDef() {
3088+ auto &pgo_dependencies = atomic_headers_[autofuse::GeneratedHeaderId::kPgo].dependencies;
3089+ for (const auto &header : {"array", "cstddef", "cstdint", "vector"}) {
3090+ autofuse::RequireSystemHeader(pgo_dependencies, header);
3091+ }
3092+ if (config_.is_autofuse) {
3093+ GenPgoHeaderCodesTail();
3094+ }
3095+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, "struct SearchConfig {");
3096+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, " bool ub_threshold_enabled = true;");
3097+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, " double ub_threshold = 0.0;");
3098+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, " bool corenum_threshold_enabled = true;");
3099+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, " double corenum_threshold = 1.0;");
3100+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, " bool enable_multicore_ub_tradeoff = true;");
3101+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kPgo, "};");
3102+}
3103+ 
2794af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &tiling_res,3104af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &tiling_res,
2795 const EnableGroupParallels &enable_group_parallels) {3105 const EnableGroupParallels &enable_group_parallels) {
2796 enable_group_parallels_ = enable_group_parallels;3106 enable_group_parallels_ = enable_group_parallels;
@@ -2798,10 +3108,7 @@ af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &
2798 FusedGraphNamespaceMap namespace_map;3108 FusedGraphNamespaceMap namespace_map;
2799 GE_ASSERT_SUCCESS(ObtainInnerParams(hardware_map, namespace_map));3109 GE_ASSERT_SUCCESS(ObtainInnerParams(hardware_map, namespace_map));
2800 // 1、生成总TilingData3110 // 1、生成总TilingData
2801- tiling_head_.Reset();3111+ InitTilingHeadCodeGeneration();
2802- tiling_func_.Reset();
2803- tiling_data_.Reset();
2804- tiling_func_.AddLine("#include \"" + kDefaultTilingHeadFileName + "\"");
2805 GE_ASSERT_SUCCESS(tiling_data_manager_.Init());3112 GE_ASSERT_SUCCESS(tiling_data_manager_.Init());
2806 if (config_.gen_tiling_data) {3113 if (config_.gen_tiling_data) {
2807 GE_ASSERT_SUCCESS(GenHeaderCodesHead(), "Generate tiling data head failed.");3114 GE_ASSERT_SUCCESS(GenHeaderCodesHead(), "Generate tiling data head failed.");
@@ -2809,13 +3116,7 @@ af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &
2809 // 2、生成公共的TilingFunc代码3116 // 2、生成公共的TilingFunc代码
2810 GE_ASSERT_SUCCESS(GenMacroInclude(), "Generate macro include failed.");3117 GE_ASSERT_SUCCESS(GenMacroInclude(), "Generate macro include failed.");
2811 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {3118 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
2812- tiling_head_.AddLine("struct SearchConfig {");3119+ GenPgoSearchConfigDef();
2813- tiling_head_.AddLine(" bool ub_threshold_enabled = true;");
2814- tiling_head_.AddLine(" double ub_threshold = 0.0;");
2815- tiling_head_.AddLine(" bool corenum_threshold_enabled = true;");
2816- tiling_head_.AddLine(" double corenum_threshold = 1.0;");
2817- tiling_head_.AddLine(" bool enable_multicore_ub_tradeoff = true;");
2818- tiling_head_.AddLine("};");
2819 }3120 }
2820 tiling_head_.AddLine("namespace optiling{};");3121 tiling_head_.AddLine("namespace optiling{};");
2821 tiling_head_.AddLine("using namespace optiling;");3122 tiling_head_.AddLine("using namespace optiling;");
@@ -2832,20 +3133,24 @@ af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &
2832 GenTilingHeadMultiGroup();3133 GenTilingHeadMultiGroup();
2833 }3134 }
2834 if (config_.enable_autofuse_pgo) {3135 if (config_.enable_autofuse_pgo) {
2835- tiling_head_.AddLine(3136+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi, "bool PGOByCoreNumSearchTilingKey(std::vector<" +
2836- "bool PGOByCoreNumSearchTilingKey(std::vector<AutofuseTilingData>& tiling_data_list, "3137+ config_.tiling_data_type_name + ">& tiling_data_list, " +
2837- "AutofuseTilingData* tiling_data, uint32_t max_block_dim);");3138+ config_.tiling_data_type_name +
3139+ "* tiling_data, uint32_t max_block_dim);");
2838 }3140 }
2839 tiling_head_.AddLine("using namespace std;");3141 tiling_head_.AddLine("using namespace std;");
2840 // 生成ArrangeBlockOffsets函数声明3142 // 生成ArrangeBlockOffsets函数声明
2841 GenArrangeBlockOffsetsDeclarations(namespace_map);3143 GenArrangeBlockOffsetsDeclarations(namespace_map);
2842 GE_ASSERT_SUCCESS(GenCommonFrameWork(), "Generate common framework failed.");3144 GE_ASSERT_SUCCESS(GenCommonFrameWork(), "Generate common framework failed.");
2843 tiling_func_.AddLine("} // namespace optiling");3145 tiling_func_.AddLine("} // namespace optiling");
3146+ for (const auto &header : {"algorithm", "cmath", "cstddef", "cstdint", "functional", "utility", "vector"}) {
3147+ RequireTranslationUnitSystemHeader(header);
3148+ }
2844 if (config_.gen_tiling_data) {3149 if (config_.gen_tiling_data) {
2845 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();3150 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();
2846 }3151 }
2847 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();3152 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();
2848- tiling_res[kTilingSolverIdentify] += tiling_func_.GetOutputStr();3153+ GE_ASSERT_SUCCESS(FinishTranslationUnit(kTilingSolverIdentify, tiling_res));
2849 return af::SUCCESS;3154 return af::SUCCESS;
2850}3155}
2851 3156 
@@ -2856,8 +3161,10 @@ void TilingCodeGenImpl::GenArrangeBlockOffsetsDeclarations(const FusedGraphNames
2856 for (const auto &result_id_and_groups : asc_graph_namespace_map) {3161 for (const auto &result_id_and_groups : asc_graph_namespace_map) {
2857 const auto &result_id = result_id_and_groups.first;3162 const auto &result_id = result_id_and_groups.first;
2858 if (enable_group_parallels_[asc_graph_id][result_id]) {3163 if (enable_group_parallels_[asc_graph_id][result_id]) {
2859- tiling_head_.AddLine("void ArrangeBlockOffsetsAscGraph" + std::to_string(asc_graph_id) + "Result" +3164+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
2860- std::to_string(result_id) + "(AutofuseTilingData &t, uint32_t aiv_num);");3165+ "void ArrangeBlockOffsetsAscGraph" + std::to_string(asc_graph_id) + "Result" +
3166+ std::to_string(result_id) + "(" + config_.tiling_data_type_name +
3167+ " &t, uint32_t aiv_num);");
2861 }3168 }
2862 }3169 }
2863 }3170 }
@@ -3386,6 +3693,7 @@ af::Status TilingCodeGenImpl::GenSingleGroupScheduleResult(
3386 if (hardware_iter != hardware_map.cend()) {3693 if (hardware_iter != hardware_map.cend()) {
3387 GenSetHardwareCodes(group_info.second.second, hardware_iter->second);3694 GenSetHardwareCodes(group_info.second.second, hardware_iter->second);
3388 if (need_update_second_group_input_vars) {3695 if (need_update_second_group_input_vars) {
3696+ RequireVarRelationSystemHeaders();
3389 std::string tiling_hyphens = check_cond.empty() ? "" : "&&";3697 std::string tiling_hyphens = check_cond.empty() ? "" : "&&";
3390 check_cond += (tiling_hyphens + "(" + input_vars_set_code + ")");3698 check_cond += (tiling_hyphens + "(" + input_vars_set_code + ")");
3391 }3699 }
@@ -3554,6 +3862,7 @@ void TilingCodeGenImpl::GenPGOByCoreNumGetScheduleResult(
3554 tiling_func_.AddLine(set_hardware_code.append(hardware_val));3862 tiling_func_.AddLine(set_hardware_code.append(hardware_val));
3555 }3863 }
3556 if (need_update_second_group_input_vars) {3864 if (need_update_second_group_input_vars) {
3865+ RequireVarRelationSystemHeaders();
3557 tiling_func_.AddLine(input_vars_set_code);3866 tiling_func_.AddLine(input_vars_set_code);
3558 }3867 }
3559 GenPGOByCoreNumDoTiling(group_info, group_index, asc_graph_id, impl_graph_id);3868 GenPGOByCoreNumDoTiling(group_info, group_index, asc_graph_id, impl_graph_id);
@@ -3607,6 +3916,7 @@ void TilingCodeGenImpl::GenFillOtherGroupsGetTiling(
3607 graph_info, var_relations_[asc_graph_id][impl_graph_id], group_iter.first, " tiling_data.",3916 graph_info, var_relations_[asc_graph_id][impl_graph_id], group_iter.first, " tiling_data.",
3608 {"valid_candidates[candidate_index - " + candidate_begin_name + "] = false;", "continue;"});3917 {"valid_candidates[candidate_index - " + candidate_begin_name + "] = false;", "continue;"});
3609 if (need_update) {3918 if (need_update) {
3919+ RequireVarRelationSystemHeaders();
3610 tiling_func_.AddLine(input_vars_set_code);3920 tiling_func_.AddLine(input_vars_set_code);
3611 }3921 }
3612 tiling_func_.AddLine(" has_solution = " + group_iter.second.first + "::GetTiling(tiling_data." +3922 tiling_func_.AddLine(" has_solution = " + group_iter.second.first + "::GetTiling(tiling_data." +
@@ -3692,6 +4002,7 @@ af::Status TilingCodeGenImpl::GenPGOScheduleGroupSearchEntry(
3692 auto [input_vars_set_code, need_update] = ProcessVarRelationsStatement(4002 auto [input_vars_set_code, need_update] = ProcessVarRelationsStatement(
3693 graph_info, var_relations_[asc_graph_id][impl_graph_id], group_info.first, " tiling_data.", {"return true;"});4003 graph_info, var_relations_[asc_graph_id][impl_graph_id], group_info.first, " tiling_data.", {"return true;"});
3694 if (need_update) {4004 if (need_update) {
4005+ RequireVarRelationSystemHeaders();
3695 tiling_func_.AddLine(input_vars_set_code);4006 tiling_func_.AddLine(input_vars_set_code);
3696 }4007 }
3697 const bool is_reuse =4008 const bool is_reuse =
@@ -3898,8 +4209,9 @@ af::Status TilingCodeGenImpl::GenEnableGroupParallelInvoke(size_t asc_graph_id,
3898af::Status TilingCodeGenImpl::GenFusedScheduleResultsGetTilingDefine(const FusedGraphNamespaceMap &namespace_map) {4209af::Status TilingCodeGenImpl::GenFusedScheduleResultsGetTilingDefine(const FusedGraphNamespaceMap &namespace_map) {
3899 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name +4210 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name +
3900 " &tiling_data, int32_t tiling_case_id, double *perf) {");4211 " &tiling_data, int32_t tiling_case_id, double *perf) {");
3901- tiling_head_.AddLine("bool GetTiling(" + config_.tiling_data_type_name +4212+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
3902- " &tiling_data, int32_t tiling_case_id, double *perf = nullptr);");4213+ "bool GetTiling(" + config_.tiling_data_type_name +
4214+ " &tiling_data, int32_t tiling_case_id, double *perf = nullptr);");
3903 4215 
3904 // 添加算子级缓存逻辑4216 // 添加算子级缓存逻辑
3905 GE_ASSERT_SUCCESS(cache::OperatorLevelCacheGen::GenInitAndQueryCacheCode(tiling_func_, tiling_model_info_, config_),4217 GE_ASSERT_SUCCESS(cache::OperatorLevelCacheGen::GenInitAndQueryCacheCode(tiling_func_, tiling_model_info_, config_),
@@ -4051,8 +4363,9 @@ af::Status TilingCodeGenImpl::GenGetTilingForAllSchedulesResults(const uint32_t
4051 const AscGraphNamepspaceMap &asc_graph_map) {4363 const AscGraphNamepspaceMap &asc_graph_map) {
4052 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4364 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +
4053 "int32_t tiling_case_id, double *perf) {");4365 "int32_t tiling_case_id, double *perf) {");
4054- tiling_head_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4366+ AddAtomicHeaderLine(
4055- "int32_t tiling_case_id, double *perf);");4367+ autofuse::GeneratedHeaderId::kApi,
4368+ "bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " + "int32_t tiling_case_id, double *perf);");
4056 tiling_func_.AddLine(" (void)perf;");4369 tiling_func_.AddLine(" (void)perf;");
4057 GE_ASSERT_SUCCESS(GenDurationBeginCode(TilingFuncDurationType::TILING_FUNC_DURATION_TOTAL, " "),4370 GE_ASSERT_SUCCESS(GenDurationBeginCode(TilingFuncDurationType::TILING_FUNC_DURATION_TOTAL, " "),
4058 "Generate begin code!");4371 "Generate begin code!");
@@ -4219,8 +4532,11 @@ void TilingCodeGenImpl::GenGetTilingFunctionSignature(const std::string &workspa
4219 }4532 }
4220 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data" + workspace_define +4533 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data" + workspace_define +
4221 ", int32_t tiling_case_id" + cache_define_func + ", double *perf) {");4534 ", int32_t tiling_case_id" + cache_define_func + ", double *perf) {");
4222- tiling_head_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data" + workspace_define +4535+ const auto header_id =
4223- ", int32_t tiling_case_id" + cache_define_head + ", double *perf = nullptr);");4536+ cache_define_head.empty() ? autofuse::GeneratedHeaderId::kApi : autofuse::GeneratedHeaderId::kState;
4537+ AddAtomicHeaderLine(header_id, "bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data" +
4538+ workspace_define + ", int32_t tiling_case_id" + cache_define_head +
4539+ ", double *perf = nullptr);");
4224}4540}
4225 4541 
4226af::Status TilingCodeGenImpl::GenGetTilingFunctionBody(bool use_cache, bool is_tail, const std::string &cache_used) {4542af::Status TilingCodeGenImpl::GenGetTilingFunctionBody(bool use_cache, bool is_tail, const std::string &cache_used) {
@@ -4436,10 +4752,23 @@ af::Status TilingCodeGenImpl::GenTilingTail(std::map<std::string, std::string> &
4436 cache_reuse_info_ = std::move(ext_params.cache_reuse_info);4752 cache_reuse_info_ = std::move(ext_params.cache_reuse_info);
4437 with_reuse_info_ = true;4753 with_reuse_info_ = true;
4438 }4754 }
4439- tiling_func_.Reset();4755+ ResetTranslationUnit();
4440 tiling_head_.Reset();4756 tiling_head_.Reset();
4441 tiling_data_.Reset();4757 tiling_data_.Reset();
4442- tiling_func_.AddLine("#include \"" + kDefaultTilingHeadFileName + "\"");4758+ if (!is_uniq_group_) {
4759+ for (const auto &header :
4760+ {"algorithm", "array", "cfloat", "cstddef", "cstdint", "functional", "unordered_map", "utility", "vector"}) {
4761+ RequireTranslationUnitSystemHeader(header);
4762+ }
4763+ RequireTranslationUnitTilingDataHeader();
4764+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kState);
4765+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kLog);
4766+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kSolver);
4767+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kApi);
4768+ if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
4769+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kPgo);
4770+ }
4771+ }
4443 tiling_func_.AddLine("namespace optiling {");4772 tiling_func_.AddLine("namespace optiling {");
4444 4773 
4445 // 支持二次Tiling:定义全局变量(多Group场景)4774 // 支持二次Tiling:定义全局变量(多Group场景)
@@ -4448,14 +4777,9 @@ af::Status TilingCodeGenImpl::GenTilingTail(std::map<std::string, std::string> &
4448 4777 
4449 GE_ASSERT_SUCCESS(GenScheduleGroupTilingTail(), "Generate tiling data tail inner failed.");4778 GE_ASSERT_SUCCESS(GenScheduleGroupTilingTail(), "Generate tiling data tail inner failed.");
4450 4779 
4451- // 生成TilingCacheContext静态成员变量定义(必须在cpp文件中,否则会链接错误)
4452- if (config_.cache_enabled_at_compile_time) {
4453- GE_ASSERT_SUCCESS(operator_level_cache_gen_->GenTilingCacheContextStaticDefs(tiling_func_),
4454- "Generate TilingCacheContext static defs failed.");
4455- }
4456 tiling_head_.AddLine("} // namespace optiling");4780 tiling_head_.AddLine("} // namespace optiling");
4457 tiling_func_.AddLine("} // namespace optiling");4781 tiling_func_.AddLine("} // namespace optiling");
4458- tiling_res[kTilingScheduleGroupTailIdentify] += tiling_func_.GetOutputStr();4782+ GE_ASSERT_SUCCESS(FinishTranslationUnit(kTilingScheduleGroupTailIdentify, tiling_res));
4459 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();4783 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();
4460 if (config_.gen_tiling_data) {4784 if (config_.gen_tiling_data) {
4461 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();4785 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();
@@ -4465,7 +4789,8 @@ af::Status TilingCodeGenImpl::GenTilingTail(std::map<std::string, std::string> &
4465 4789 
4466af::Status TilingCodeGenImpl::GenGetPerf() {4790af::Status TilingCodeGenImpl::GenGetPerf() {
4467 tiling_func_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data) {");4791 tiling_func_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data) {");
4468- tiling_head_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data);");4792+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
4793+ "double GetPerf(" + config_.tiling_data_type_name + " &tiling_data);");
4469 tiling_func_.AddLine(4794 tiling_func_.AddLine(
4470 " TilingCaseImplPtr tilingCaseImplPtr = GetTilingImplPtr(tiling_data.get_tiling_key(), "4795 " TilingCaseImplPtr tilingCaseImplPtr = GetTilingImplPtr(tiling_data.get_tiling_key(), "
4471 "tiling_data.get_block_dim());");4796 "tiling_data.get_block_dim());");
@@ -4476,7 +4801,8 @@ af::Status TilingCodeGenImpl::GenGetPerf() {
4476 4801 
4477af::Status TilingCodeGenImpl::GenGetSummary() {4802af::Status TilingCodeGenImpl::GenGetSummary() {
4478 tiling_func_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data) {");4803 tiling_func_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data) {");
4479- tiling_head_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data);");4804+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
4805+ "void GetSummary(" + config_.tiling_data_type_name + " &tiling_data);");
4480 tiling_func_.AddLine(4806 tiling_func_.AddLine(
4481 " TilingCaseImplPtr tilingCaseImplPtr = GetTilingImplPtr(tiling_data.get_tiling_key(), "4807 " TilingCaseImplPtr tilingCaseImplPtr = GetTilingImplPtr(tiling_data.get_tiling_key(), "
4482 "tiling_data.get_block_dim());");4808 "tiling_data.get_block_dim());");
@@ -4511,6 +4837,93 @@ af::Status TilingCodeGenImpl::GenTilingKeyFunc() {
4511 return af::SUCCESS;4837 return af::SUCCESS;
4512}4838}
4513 4839 
4840+af::Status TilingCodeGenImpl::InitTilingGeneration(const std::unordered_map<std::string, std::string> &cache_reuse_info,
4841+ uint32_t cache_capacity) {
4842+ cache_capacity_ = cache_capacity;
4843+ if (!cache_reuse_info.empty()) {
4844+ cache_reuse_info_ = cache_reuse_info;
4845+ with_reuse_info_ = true;
4846+ }
4847+ tiling_head_.Reset();
4848+ ResetTranslationUnit();
4849+ tiling_data_.Reset();
4850+ GE_ASSERT_TRUE(!tiling_model_info_.empty());
4851+ GE_ASSERT_SUCCESS(tiling_data_manager_.Init());
4852+ GE_ASSERT_SUCCESS(GenScheduleGroupTilingHead());
4853+ return af::SUCCESS;
4854+}
4855+ 
4856+void TilingCodeGenImpl::GenGroupNamespaceHead(const ScheduleGroupIdent &cur_ident) {
4857+ tiling_func_.AddLine("namespace optiling{");
4858+ // 支持二次Tiling:extern声明全局变量(定义在第一个namespace optiling中)
4859+ tiling_func_.AddLine("// 支持二次Tiling:全局变量,用于传递调整后的核数比例");
4860+ tiling_func_.AddLine("extern thread_local double g_secondary_tiling_ratio;");
4861+ if (!is_uniq_group_) {
4862+ const std::string tiling_data_forward_decl = "struct " + config_.tiling_data_type_name + ";\n";
4863+ if (config_.is_autofuse) {
4864+ const std::string global_forward_decl =
4865+ "} // namespace optiling\n" + tiling_data_forward_decl + "namespace optiling {\n";
4866+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, global_forward_decl);
4867+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kApi, global_forward_decl);
4868+ } else {
4869+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, tiling_data_forward_decl);
4870+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kApi, tiling_data_forward_decl);
4871+ }
4872+ autofuse::RequireSystemHeader(atomic_headers_[autofuse::GeneratedHeaderId::kState].dependencies, "unordered_map");
4873+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi, "namespace " + cur_ident.GetGroupPrefix() + " {");
4874+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, "namespace " + cur_ident.GetGroupPrefix() + " {\n");
4875+ tiling_func_.AddLine("namespace " + cur_ident.GetGroupPrefix() + " {");
4876+ }
4877+}
4878+ 
4879+void TilingCodeGenImpl::RequireReuseGroupTranslationUnitHeaders() {
4880+ for (const auto &header : {"cstdint", "unordered_map"}) {
4881+ RequireTranslationUnitSystemHeader(header);
4882+ }
4883+ RequireTranslationUnitTilingDataHeader();
4884+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kState);
4885+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kSolver);
4886+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kApi);
4887+}
4888+ 
4889+void TilingCodeGenImpl::RequireGroupTranslationUnitHeaders() {
4890+ for (const auto &header : {"algorithm", "cstdint", "map", "memory", "string", "unordered_map", "vector"}) {
4891+ RequireTranslationUnitSystemHeader(header);
4892+ }
4893+ if (hardware_has_ub_) {
4894+ RequireTranslationUnitSystemHeader("cmath");
4895+ }
4896+ if (with_reuse_info_ || config_.cache_enabled_at_compile_time) {
4897+ RequireTranslationUnitSystemHeader("array");
4898+ }
4899+ if (config_.cache_enabled_at_compile_time) {
4900+ RequireTranslationUnitSystemHeader("cstring");
4901+ }
4902+ RequireTranslationUnitTilingDataHeader();
4903+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kState);
4904+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kLog);
4905+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kSolver);
4906+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kApi);
4907+ if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
4908+ for (const auto &header : {"cfloat", "cstddef", "cstdlib", "new"}) {
4909+ RequireTranslationUnitSystemHeader(header);
4910+ }
4911+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kPgo);
4912+ }
4913+}
4914+ 
4915+af::Status TilingCodeGenImpl::FinishGroupTiling(const ScheduleGroupIdent &cur_ident,
4916+ std::map<std::string, std::string> &tiling_res) {
4917+ tiling_func_.AddLine("} // namespace optiling");
4918+ if (config_.gen_tiling_data) {
4919+ tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();
4920+ }
4921+ tiling_res[cur_ident.GetGroupPrefixSnakeCase()].clear();
4922+ GE_ASSERT_SUCCESS(FinishTranslationUnit(cur_ident.GetGroupPrefixSnakeCase(), tiling_res));
4923+ tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();
4924+ return af::SUCCESS;
4925+}
4926+ 
4514af::Status TilingCodeGenImpl::GenTiling(std::map<std::string, std::string> &tiling_res,4927af::Status TilingCodeGenImpl::GenTiling(std::map<std::string, std::string> &tiling_res,
4515 std::unordered_map<std::string, std::string> cache_reuse_info,4928 std::unordered_map<std::string, std::string> cache_reuse_info,
4516 uint32_t cache_capacity, const EnableGroupParallels &enable_group_parallels) {4929 uint32_t cache_capacity, const EnableGroupParallels &enable_group_parallels) {
@@ -4518,50 +4931,32 @@ af::Status TilingCodeGenImpl::GenTiling(std::map<std::string, std::string> &tili
4518 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {4931 if (config_.enable_autofuse_pgo || config_.is_inductor_scene) {
4519 GE_ASSERT_SUCCESS(GenEnableGroupParallelPgoInvoke("autofuse_tiling_data", true, " ", arrange_code_));4932 GE_ASSERT_SUCCESS(GenEnableGroupParallelPgoInvoke("autofuse_tiling_data", true, " ", arrange_code_));
4520 }4933 }
4521- cache_capacity_ = cache_capacity;4934+ GE_ASSERT_SUCCESS(InitTilingGeneration(cache_reuse_info, cache_capacity));
4522- if (!(cache_reuse_info.empty())) {
4523- cache_reuse_info_ = cache_reuse_info;
4524- with_reuse_info_ = true;
4525- }
4526- // make sure input model info is valid
4527- tiling_head_.Reset();
4528- tiling_func_.Reset();
4529- tiling_data_.Reset();
4530- GE_ASSERT_TRUE(!tiling_model_info_.empty());
4531- GE_ASSERT_SUCCESS(tiling_data_manager_.Init());
4532- GE_ASSERT_SUCCESS(GenScheduleGroupTilingHead());
4533 const auto &cur_ident = tiling_model_info_[0].schedule_group_ident;4935 const auto &cur_ident = tiling_model_info_[0].schedule_group_ident;
4534- tiling_func_.AddLine("#include \"" + kDefaultTilingHeadFileName + "\"");4936+ GenGroupNamespaceHead(cur_ident);
4535- tiling_func_.AddLine("namespace optiling{");
4536- // 支持二次Tiling:extern声明全局变量(定义在第一个namespace optiling中)
4537- tiling_func_.AddLine("// 支持二次Tiling:全局变量,用于传递调整后的核数比例");
4538- tiling_func_.AddLine("extern thread_local double g_secondary_tiling_ratio;");
4539- if (!is_uniq_group_) {
4540- tiling_head_.AddLine("namespace " + cur_ident.GetGroupPrefix() + " {");
4541- tiling_func_.AddLine("namespace " + cur_ident.GetGroupPrefix() + " {");
4542- }
4543 GELOGD("Generate tiling code for %s of %s reuse_ident is %s.", cur_ident.GetGroupPrefix().c_str(), op_name_.c_str(),4937 GELOGD("Generate tiling code for %s of %s reuse_ident is %s.", cur_ident.GetGroupPrefix().c_str(), op_name_.c_str(),
4544 tiling_model_info_[0].reuse_schedule_group->reuse_group_ident.GetGroupPrefix().c_str());4938 tiling_model_info_[0].reuse_schedule_group->reuse_group_ident.GetGroupPrefix().c_str());
4545 if (tiling_model_info_[0].reuse_schedule_group->IsReuseGroup(cur_ident)) {4939 if (tiling_model_info_[0].reuse_schedule_group->IsReuseGroup(cur_ident)) {
4940+ RequireReuseGroupTranslationUnitHeaders();
4546 if (config_.enable_autofuse_pgo) {4941 if (config_.enable_autofuse_pgo) {
4942+ RequireTranslationUnitSystemHeader("cfloat");
4943+ RequireTranslationUnitSystemHeader("vector");
4944+ RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId::kPgo);
4547 GE_ASSERT_SUCCESS(GenPGOReuseGroupTilingWrapper(), "Generate func call entrance failed.");4945 GE_ASSERT_SUCCESS(GenPGOReuseGroupTilingWrapper(), "Generate func call entrance failed.");
4548 }4946 }
4549 return GenReuseGroupTilingWrapper(tiling_res);4947 return GenReuseGroupTilingWrapper(tiling_res);
4550 }4948 }
4949+ RequireGroupTranslationUnitHeaders();
4950+ AddApiTilingPreambles();
4551 GE_ASSERT_SUCCESS(GenTilingKeyFunc());4951 GE_ASSERT_SUCCESS(GenTilingKeyFunc());
4552 GE_ASSERT_SUCCESS(GenGetPerf(), "Generate getperf failed.");4952 GE_ASSERT_SUCCESS(GenGetPerf(), "Generate getperf failed.");
4553 if (!is_uniq_group_) {4953 if (!is_uniq_group_) {
4554 GE_ASSERT_SUCCESS(GenGetSummary(), "Generate getsummary failed.");4954 GE_ASSERT_SUCCESS(GenGetSummary(), "Generate getsummary failed.");
4555- tiling_head_.AddLine("} // namespace " + cur_ident.GetGroupPrefix());4955+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, "} // namespace " + cur_ident.GetGroupPrefix() + "\n");
4956+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi, "} // namespace " + cur_ident.GetGroupPrefix());
4556 tiling_func_.AddLine("} // namespace " + cur_ident.GetGroupPrefix());4957 tiling_func_.AddLine("} // namespace " + cur_ident.GetGroupPrefix());
4557 }4958 }
4558- tiling_func_.AddLine("} // namespace optiling");4959+ return FinishGroupTiling(cur_ident, tiling_res);
4559- if (config_.gen_tiling_data) {
4560- tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();
4561- }
4562- tiling_res[cur_ident.GetGroupPrefixSnakeCase()] = tiling_func_.GetOutputStr();
4563- tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();
4564- return af::SUCCESS;
4565}4960}
4566 4961 
4567af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetTiling(4962af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetTiling(
@@ -4571,16 +4966,18 @@ af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetTiling(
4571 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4966 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +
4572 (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +4967 (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +
4573 "int32_t tiling_case_id, " + reuse_prefix + "::GroupLevelCache* cache) {");4968 "int32_t tiling_case_id, " + reuse_prefix + "::GroupLevelCache* cache) {");
4574- tiling_head_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4969+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kState,
4575- (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +4970+ "bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +
4576- "int32_t tiling_case_id, " + reuse_prefix + "::GroupLevelCache* cache = nullptr);");4971+ (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +
4972+ "int32_t tiling_case_id, " + reuse_prefix + "::GroupLevelCache* cache = nullptr);");
4577 } else {4973 } else {
4578 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4974 tiling_func_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +
4579 (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +4975 (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +
4580 "int32_t tiling_case_id) {");4976 "int32_t tiling_case_id) {");
4581- tiling_head_.AddLine("bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +4977+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
4582- (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +4978+ "bool GetTiling(" + config_.tiling_data_type_name + " &tiling_data, " +
4583- "int32_t tiling_case_id);");4979+ (is_uniq_group_ ? "" : "std::unordered_map<int64_t, uint64_t> &workspace_map, ") +
4980+ "int32_t tiling_case_id);");
4584 }4981 }
4585 auto reuse_tiling_data =4982 auto reuse_tiling_data =
4586 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";4983 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";
@@ -4600,7 +4997,8 @@ af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetPerf(
4600 const std::string &cur_prefix, const std::string &reuse_prefix, const ReuseScheduleGroupInfo &reuse_info,4997 const std::string &cur_prefix, const std::string &reuse_prefix, const ReuseScheduleGroupInfo &reuse_info,
4601 std::map<ScheduleGroupIdent, ReuseScheduleGroupInfo>::const_iterator iter) {4998 std::map<ScheduleGroupIdent, ReuseScheduleGroupInfo>::const_iterator iter) {
4602 tiling_func_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data) {");4999 tiling_func_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data) {");
4603- tiling_head_.AddLine("double GetPerf(" + config_.tiling_data_type_name + " &tiling_data);");5000+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
5001+ "double GetPerf(" + config_.tiling_data_type_name + " &tiling_data);");
4604 auto reuse_tiling_data =5002 auto reuse_tiling_data =
4605 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";5003 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";
4606 tiling_func_.AddLine(reuse_tiling_data);5004 tiling_func_.AddLine(reuse_tiling_data);
@@ -4614,7 +5012,8 @@ af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetSummary(
4614 const std::string &cur_prefix, const std::string &reuse_prefix, const ReuseScheduleGroupInfo &reuse_info,5012 const std::string &cur_prefix, const std::string &reuse_prefix, const ReuseScheduleGroupInfo &reuse_info,
4615 std::map<ScheduleGroupIdent, ReuseScheduleGroupInfo>::const_iterator iter) {5013 std::map<ScheduleGroupIdent, ReuseScheduleGroupInfo>::const_iterator iter) {
4616 tiling_func_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data) {");5014 tiling_func_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data) {");
4617- tiling_head_.AddLine("void GetSummary(" + config_.tiling_data_type_name + " &tiling_data);");5015+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi,
5016+ "void GetSummary(" + config_.tiling_data_type_name + " &tiling_data);");
4618 auto reuse_tiling_data =5017 auto reuse_tiling_data =
4619 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";5018 " auto reuse_tiling_data = RefToRef<" + cur_prefix + "TilingData, " + reuse_prefix + "TilingData>(tiling_data);";
4620 tiling_func_.AddLine(reuse_tiling_data);5019 tiling_func_.AddLine(reuse_tiling_data);
@@ -4648,13 +5047,15 @@ af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapper(std::map<std::string, s
4648 GE_ASSERT_SUCCESS(GenReuseGroupTilingWrapperGetPerf(cur_prefix, reuse_prefix, reuse_info, iter));5047 GE_ASSERT_SUCCESS(GenReuseGroupTilingWrapperGetPerf(cur_prefix, reuse_prefix, reuse_info, iter));
4649 // Gen GetSummary5048 // Gen GetSummary
4650 GE_ASSERT_SUCCESS(GenReuseGroupTilingWrapperGetSummary(cur_prefix, reuse_prefix, reuse_info, iter));5049 GE_ASSERT_SUCCESS(GenReuseGroupTilingWrapperGetSummary(cur_prefix, reuse_prefix, reuse_info, iter));
4651- tiling_head_.AddLine("} // namespace " + cur_prefix);5050+ AppendAtomicHeaderBody(autofuse::GeneratedHeaderId::kState, "} // namespace " + cur_prefix + "\n");
5051+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi, "} // namespace " + cur_prefix);
4652 tiling_func_.AddLine("} // namespace " + cur_prefix);5052 tiling_func_.AddLine("} // namespace " + cur_prefix);
4653 tiling_func_.AddLine("} // namespace optiling");5053 tiling_func_.AddLine("} // namespace optiling");
4654 if (config_.gen_tiling_data) {5054 if (config_.gen_tiling_data) {
4655 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();5055 tiling_res[config_.tiling_data_type_name] += tiling_data_.GetOutputStr();
4656 }5056 }
4657- tiling_res[cur_ident.GetGroupPrefixSnakeCase()] = tiling_func_.GetOutputStr();5057+ tiling_res[cur_ident.GetGroupPrefixSnakeCase()].clear();
5058+ GE_ASSERT_SUCCESS(FinishTranslationUnit(cur_ident.GetGroupPrefixSnakeCase(), tiling_res));
4658 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();5059 tiling_res[kTilingHeadIdentify] += tiling_head_.GetOutputStr();
4659 GELOGD("Generate reuse group tiling wrapper for %s of %s success.", cur_prefix.c_str(), op_name_.c_str());5060 GELOGD("Generate reuse group tiling wrapper for %s of %s success.", cur_prefix.c_str(), op_name_.c_str());
4660 return af::SUCCESS;5061 return af::SUCCESS;
@@ -4673,8 +5074,8 @@ af::Status TilingCodeGenImpl::GenPGOReuseGroupTilingWrapper() {
4673 // Gen PGOProfileReuseGroup: reuse group does not search, only profiles by copying from primary group5074 // Gen PGOProfileReuseGroup: reuse group does not search, only profiles by copying from primary group
4674 std::string pgo_profile_sig =5075 std::string pgo_profile_sig =
4675 std::string("bool PGOProfileReuseGroup(std::vector<AutofuseTilingDataPerf>& tiling_data_list, ") +5076 std::string("bool PGOProfileReuseGroup(std::vector<AutofuseTilingDataPerf>& tiling_data_list, ") +
4676- "AutofuseTilingData* output_tiling_data, void* stream, uint32_t workspaceSize, double& best_perf)";5077+ config_.tiling_data_type_name + "* output_tiling_data, void* stream, uint32_t workspaceSize, double& best_perf)";
4677- tiling_head_.AddLine(pgo_profile_sig + ";");5078+ AddAtomicHeaderLine(autofuse::GeneratedHeaderId::kApi, pgo_profile_sig + ";");
4678 tiling_func_.AddLine(pgo_profile_sig + " {");5079 tiling_func_.AddLine(pgo_profile_sig + " {");
4679 tiling_func_.AddLine(" double cur_perf = DBL_MAX;");5080 tiling_func_.AddLine(" double cur_perf = DBL_MAX;");
4680 tiling_func_.AddLine(" AutofuseTilingData autofuse_tiling_data_tmp = *output_tiling_data;");5081 tiling_func_.AddLine(" AutofuseTilingData autofuse_tiling_data_tmp = *output_tiling_data;");
@@ -16,6 +16,7 @@
16#include <memory>16#include <memory>
17#include <utility>17#include <utility>
18#include "code_printer.h"18#include "code_printer.h"
19+#include "common/tiling_source_dependencies.h"
19#include "base/model_info.h"20#include "base/model_info.h"
20#include "generator_config.h"21#include "generator_config.h"
21#include "tiling_data_gen/tiling_data_generator.h"22#include "tiling_data_gen/tiling_data_generator.h"
@@ -58,6 +59,13 @@ class TilingCodeGenImpl {
58 af::Status GenTiling(std::map<std::string, std::string> &tiling_res,59 af::Status GenTiling(std::map<std::string, std::string> &tiling_res,
59 std::unordered_map<std::string, std::string> cache_reuse_info = {}, uint32_t cache_capacity = 0,60 std::unordered_map<std::string, std::string> cache_reuse_info = {}, uint32_t cache_capacity = 0,
60 const EnableGroupParallels &enable_group_parallels = {});61 const EnableGroupParallels &enable_group_parallels = {});
62+ af::Status FinishGeneratedHeaders(std::map<std::string, std::string> &tiling_res);
63+ static af::Status FinishGeneratedHeaders(
64+ const std::map<autofuse::GeneratedHeaderId, autofuse::GeneratedCode> &generated_headers,
65+ const std::string &tiling_data_type_name, bool is_autofuse, std::map<std::string, std::string> &tiling_res);
66+ const std::map<autofuse::GeneratedHeaderId, autofuse::GeneratedCode> &GetGeneratedHeaders() const {
67+ return atomic_headers_;
68+ }
61 69 
62 // 设置每个ScheduleResult的Group个数70 // 设置每个ScheduleResult的Group个数
63 void SetScheduleResultGroupNums(const std::map<std::pair<size_t, size_t>, size_t> &group_nums) {71 void SetScheduleResultGroupNums(const std::map<std::pair<size_t, size_t>, size_t> &group_nums) {
@@ -68,11 +76,22 @@ class TilingCodeGenImpl {
68 uint32_t GetGroupNumForCurrentScheduleResult(const std::pair<size_t, size_t> &schedule_result_key) const;76 uint32_t GetGroupNumForCurrentScheduleResult(const std::pair<size_t, size_t> &schedule_result_key) const;
69 77 
70 protected:78 protected:
79+ void AddAtomicHeaderLine(autofuse::GeneratedHeaderId header_id, const std::string &line);
80+ void AppendAtomicHeaderBody(autofuse::GeneratedHeaderId header_id, const std::string &body);
81+ void ResetTranslationUnit();
82+ void RequireTranslationUnitSystemHeader(const std::string &header);
83+ void RequireVarRelationSystemHeaders();
84+ void RequireTranslationUnitExternalHeader(const std::string &header);
85+ void RequireTranslationUnitGeneratedHeader(autofuse::GeneratedHeaderId header_id);
86+ void RequireTranslationUnitTilingDataHeader();
87+ void AddApiTilingPreambles();
88+ af::Status FinishTranslationUnit(const std::string &key, std::map<std::string, std::string> &tiling_res);
71 // 用于判断求解器是否有效89 // 用于判断求解器是否有效
72 af::Status CheckImplPtr(const std::string &indent);90 af::Status CheckImplPtr(const std::string &indent);
73 af::Status GetReuseVarNames(std::map<std::string, std::string> &var_names_to_reuse_var_name);91 af::Status GetReuseVarNames(std::map<std::string, std::string> &var_names_to_reuse_var_name);
74 // 用于构造一个用于复制的结构体92 // 用于构造一个用于复制的结构体
75 af::Status GenStructCopyDef();93 af::Status GenStructCopyDef();
94+ af::Status CollectStructCopyVars(std::set<std::string> &tiling_data_vars);
76 // 用于构造一个用于缓存复用的哈希表95 // 用于构造一个用于缓存复用的哈希表
77 af::Status GenCacheHashMapDef();96 af::Status GenCacheHashMapDef();
78 97 
@@ -243,6 +262,8 @@ class TilingCodeGenImpl {
243 // 生成宏函数与include信息262 // 生成宏函数与include信息
244 virtual af::Status GenMacroInclude();263 virtual af::Status GenMacroInclude();
245 void GenPgoHeaderCodesTail();264 void GenPgoHeaderCodesTail();
265+ void GenPgoCallbackDefs(ge::CodePrinter &pgo_header);
266+ void GenPgoConfigDefs(ge::CodePrinter &pgo_header);
246 // 生成工具函数267 // 生成工具函数
247 virtual af::Status GenToolFuncs();268 virtual af::Status GenToolFuncs();
248 // 生成tilingimpl的基类public函数269 // 生成tilingimpl的基类public函数
@@ -318,6 +339,8 @@ class TilingCodeGenImpl {
318 ge::CodePrinter tiling_data_;339 ge::CodePrinter tiling_data_;
319 ge::CodePrinter tiling_func_;340 ge::CodePrinter tiling_func_;
320 ge::CodePrinter tiling_head_;341 ge::CodePrinter tiling_head_;
342+ std::map<autofuse::GeneratedHeaderId, autofuse::GeneratedCode> atomic_headers_;
343+ autofuse::GeneratedCode translation_unit_;
321 std::string op_name_;344 std::string op_name_;
322 TilingCodeGenConfig config_;345 TilingCodeGenConfig config_;
323 ExtraInfoConfig extra_info_config_;346 ExtraInfoConfig extra_info_config_;
@@ -412,6 +435,14 @@ class TilingCodeGenImpl {
412 af::Status GenPGOReuseGroupTilingWrapper();435 af::Status GenPGOReuseGroupTilingWrapper();
413 af::Status GenTilingKeyFunc();436 af::Status GenTilingKeyFunc();
414 void GenTilingHeadMultiGroup();437 void GenTilingHeadMultiGroup();
438+ void InitTilingHeadCodeGeneration();
439+ void GenPgoSearchConfigDef();
440+ af::Status InitTilingGeneration(const std::unordered_map<std::string, std::string> &cache_reuse_info,
441+ uint32_t cache_capacity);
442+ void GenGroupNamespaceHead(const ScheduleGroupIdent &cur_ident);
443+ void RequireReuseGroupTranslationUnitHeaders();
444+ void RequireGroupTranslationUnitHeaders();
445+ af::Status FinishGroupTiling(const ScheduleGroupIdent &cur_ident, std::map<std::string, std::string> &tiling_res);
415 446 
416 // 辅助函数:从所有model info中收集输入变量名并返回数量447 // 辅助函数:从所有model info中收集输入变量名并返回数量
417 size_t CollectInputVarsSize() const;448 size_t CollectInputVarsSize() const;
@@ -31,6 +31,25 @@ bool IsUniqueGroups(const TilingModelInfo &all_model_infos) {
31 }31 }
32 return (asc_graphs.size() == 1UL) && (groups_ids.size() == 1UL) && (impl_graphs_ids.size() == 1UL);32 return (asc_graphs.size() == 1UL) && (groups_ids.size() == 1UL) && (impl_graphs_ids.size() == 1UL);
33}33}
34+ 
35+std::string GetSplitHeaderFileName(const std::string &key) {
36+ if (key == kTilingStateHeaderIdentify) {
37+ return kTilingStateHeaderFileName;
38+ }
39+ if (key == kTilingLogHeaderIdentify) {
40+ return kTilingLogHeaderFileName;
41+ }
42+ if (key == kTilingPgoHeaderIdentify) {
43+ return kTilingPgoHeaderFileName;
44+ }
45+ if (key == kTilingApiHeaderIdentify) {
46+ return kTilingApiHeaderFileName;
47+ }
48+ if (key == kTilingSolverHeaderIdentify) {
49+ return kTilingSolverHeaderFileName;
50+ }
51+ return "";
52+}
34} // namespace53} // namespace
35 54 
36af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type, const TilingModelInfo &model_infos,55af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type, const TilingModelInfo &model_infos,
@@ -52,6 +71,9 @@ af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type, const
52 if (key == kTilingHeadIdentify) {71 if (key == kTilingHeadIdentify) {
53 tiling_dumper.AddLine(value);72 tiling_dumper.AddLine(value);
54 tiling_dumper.SaveToFile(kDefaultTilingHeadFileName);73 tiling_dumper.SaveToFile(kDefaultTilingHeadFileName);
74+ } else if (!GetSplitHeaderFileName(key).empty()) {
75+ tiling_dumper.AddLine(value);
76+ tiling_dumper.SaveToFile(EnsureTrailingSlash(config.path) + GetSplitHeaderFileName(key));
55 } else if ((key == config.tiling_data_type_name) || (key.find(kDefaultTilingDataTypeName) != std::string::npos)) {77 } else if ((key == config.tiling_data_type_name) || (key.find(kDefaultTilingDataTypeName) != std::string::npos)) {
56 // doning nothing,在上面做过处理了78 // doning nothing,在上面做过处理了
57 } else {79 } else {
@@ -77,6 +99,7 @@ af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type, const
77 GE_ASSERT_SUCCESS(impl->GenTilingTail(tiling_res), "Gen tiling tail impl failed, type[%d].",99 GE_ASSERT_SUCCESS(impl->GenTilingTail(tiling_res), "Gen tiling tail impl failed, type[%d].",
78 static_cast<int32_t>(config.type));100 static_cast<int32_t>(config.type));
79 GE_ASSERT_TRUE(tiling_res.find(kTilingHeadIdentify) != tiling_res.cend(), "Generate tiling func failed.");101 GE_ASSERT_TRUE(tiling_res.find(kTilingHeadIdentify) != tiling_res.cend(), "Generate tiling func failed.");
102+ GE_ASSERT_SUCCESS(impl->FinishGeneratedHeaders(tiling_res), "Finish generated tiling headers failed.");
80 return af::SUCCESS;103 return af::SUCCESS;
81}104}
82 105 
@@ -177,6 +200,7 @@ af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type,
177 return GenTilingCode(op_type, all_model_infos, config, tiling_res);200 return GenTilingCode(op_type, all_model_infos, config, tiling_res);
178 }201 }
179 202 
203+ generated_headers_.clear();
180 GenTilingHead(op_type, all_model_infos, config, tiling_res, enable_group_parallels);204 GenTilingHead(op_type, all_model_infos, config, tiling_res, enable_group_parallels);
181 GELOGD("Got model infos size %zu of op type = %s.", all_model_infos.size(), op_type.c_str());205 GELOGD("Got model infos size %zu of op type = %s.", all_model_infos.size(), op_type.c_str());
182 206 
@@ -190,6 +214,9 @@ af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type,
190 GenTilingTailExtParams ext_params = {schedule_result_score_func, var_relations, enable_group_parallels,214 GenTilingTailExtParams ext_params = {schedule_result_score_func, var_relations, enable_group_parallels,
191 workspace_tensor_id_set};215 workspace_tensor_id_set};
192 GenTilingTail(params, tiling_res, ext_params);216 GenTilingTail(params, tiling_res, ext_params);
217+ GE_ASSERT_SUCCESS(TilingCodeGenImpl::FinishGeneratedHeaders(generated_headers_, config.tiling_data_type_name,
218+ config.is_autofuse, tiling_res),
219+ "Finish generated tiling headers failed.");
193 return af::SUCCESS;220 return af::SUCCESS;
194}221}
195 222 
@@ -203,6 +230,7 @@ af::Status TilingCodeGenerator::GenTilingHead(const std::string &op_type, const
203 GE_ASSERT_NOTNULL(impl, "Create tiling code gen impl failed, type[%d].", static_cast<int32_t>(config.type));230 GE_ASSERT_NOTNULL(impl, "Create tiling code gen impl failed, type[%d].", static_cast<int32_t>(config.type));
204 GE_ASSERT_SUCCESS(impl->GenTilingHead(tiling_res, enable_group_parallels), "Gen tiling head impl failed, type[%d].",231 GE_ASSERT_SUCCESS(impl->GenTilingHead(tiling_res, enable_group_parallels), "Gen tiling head impl failed, type[%d].",
205 static_cast<int32_t>(config.type));232 static_cast<int32_t>(config.type));
233+ MergeGeneratedHeaders(*impl);
206 return af::SUCCESS;234 return af::SUCCESS;
207}235}
208 236 
@@ -217,6 +245,7 @@ af::Status TilingCodeGenerator::GenTilingBody(const GenTilingParams &params,
217 245 
218 GE_ASSERT_SUCCESS(impl->GenTiling(tiling_res, params.cache_reuse_info, cache_capacity, enable_group_parallels),246 GE_ASSERT_SUCCESS(impl->GenTiling(tiling_res, params.cache_reuse_info, cache_capacity, enable_group_parallels),
219 "Gen tiling body impl failed, type[%d].", static_cast<int32_t>(params.config.type));247 "Gen tiling body impl failed, type[%d].", static_cast<int32_t>(params.config.type));
248+ MergeGeneratedHeaders(*impl);
220 return af::SUCCESS;249 return af::SUCCESS;
221}250}
222 251 
@@ -232,9 +261,16 @@ af::Status TilingCodeGenerator::GenTilingTail(const GenTilingParams &params,
232 std::move(ext_params.workspace_tensor_id_set)};261 std::move(ext_params.workspace_tensor_id_set)};
233 GE_ASSERT_SUCCESS(impl->GenTilingTail(tiling_res, impl_ext_params), "Gen tiling tail impl failed, type[%d].",262 GE_ASSERT_SUCCESS(impl->GenTilingTail(tiling_res, impl_ext_params), "Gen tiling tail impl failed, type[%d].",
234 static_cast<int32_t>(params.config.type));263 static_cast<int32_t>(params.config.type));
264+ MergeGeneratedHeaders(*impl);
235 return af::SUCCESS;265 return af::SUCCESS;
236}266}
237 267 
268+void TilingCodeGenerator::MergeGeneratedHeaders(const TilingCodeGenImpl &impl) {
269+ for (const auto &[header_id, generated_code] : impl.GetGeneratedHeaders()) {
270+ autofuse::AppendGeneratedCode(generated_headers_[header_id], generated_code);
271+ }
272+}
273+ 
238af::Status TilingCodeGenerator::CollectModelInfosAndMetadata(274af::Status TilingCodeGenerator::CollectModelInfosAndMetadata(
239 const FusedParsedScheduleResult &fused_parsed_schedule_result, TilingModelInfo &all_model_infos, size_t &group_num,275 const FusedParsedScheduleResult &fused_parsed_schedule_result, TilingModelInfo &all_model_infos, size_t &group_num,
240 ScoreFuncs &schedule_result_score_func, VarRelations &var_relations, EnableGroupParallels &enable_group_parallels,276 ScoreFuncs &schedule_result_score_func, VarRelations &var_relations, EnableGroupParallels &enable_group_parallels,
@@ -291,6 +327,7 @@ af::Status TilingCodeGenerator::GenScheduleGroupTilingBodies(
291 impl->SetScheduleResultGroupNums(schedule_result_group_nums);327 impl->SetScheduleResultGroupNums(schedule_result_group_nums);
292 GE_ASSERT_SUCCESS(impl->GenTiling(tiling_res, params.cache_reuse_info, cache_capacity, enable_group_parallels),328 GE_ASSERT_SUCCESS(impl->GenTiling(tiling_res, params.cache_reuse_info, cache_capacity, enable_group_parallels),
293 "Gen tiling body impl failed, type[%d].", params.config.type);329 "Gen tiling body impl failed, type[%d].", params.config.type);
330+ MergeGeneratedHeaders(*impl);
294 tiling_res[config.tiling_data_type_name] += tiling_res[cur_config.tiling_data_type_name];331 tiling_res[config.tiling_data_type_name] += tiling_res[cur_config.tiling_data_type_name];
295 }332 }
296 }333 }
@@ -70,6 +70,9 @@ class TilingCodeGenerator {
70 const std::unordered_map<std::string, std::string> &cache_reuse_info,70 const std::unordered_map<std::string, std::string> &cache_reuse_info,
71 uint32_t cache_capacity, const EnableGroupParallels &enable_group_parallels,71 uint32_t cache_capacity, const EnableGroupParallels &enable_group_parallels,
72 std::map<std::string, std::string> &tiling_res);72 std::map<std::string, std::string> &tiling_res);
73+ void MergeGeneratedHeaders(const TilingCodeGenImpl &impl);
74+ 
75+ std::map<autofuse::GeneratedHeaderId, autofuse::GeneratedCode> generated_headers_;
73};76};
74} // namespace att77} // namespace att
75#endif78#endif
@@ -106,6 +106,14 @@ Status EnrichScheduledResultAscirParams(const ascir::FusedScheduledResult &fused
106 return af::SUCCESS;106 return af::SUCCESS;
107}107}
108 108 
109+bool IsSplitTilingHeaderKey(const std::string &key) {
110+ return key == kTilingStateHeaderIdentify || key == kTilingLogHeaderIdentify || key == kTilingPgoHeaderIdentify ||
111+ key == kTilingSolverHeaderIdentify || key == kTilingApiHeaderIdentify || key == kTilingBaseHeaderIdentify ||
112+ key == kTilingEntryHeaderIdentify || key == kTilingTailHeaderIdentify;
113+}
114+ 
115+std::string RemoveSplitCppIncludes(const std::string &content);
116+ 
109Status CombineTilings(const std::map<std::string, std::string> &tiling_file_name_to_content, std::string &result) {117Status CombineTilings(const std::map<std::string, std::string> &tiling_file_name_to_content, std::string &result) {
110 GE_CHK_BOOL_RET_STATUS(tiling_file_name_to_content.find(kTilingHeadIdentify) != tiling_file_name_to_content.end(),118 GE_CHK_BOOL_RET_STATUS(tiling_file_name_to_content.find(kTilingHeadIdentify) != tiling_file_name_to_content.end(),
111 af::FAILED, "tiling_file_name_to_content has no tiling head");119 af::FAILED, "tiling_file_name_to_content has no tiling head");
@@ -114,23 +122,12 @@ Status CombineTilings(const std::map<std::string, std::string> &tiling_file_name
114 122 
115 // 遍历所有非 TilingHead 和 TilingData 的条目,去掉第一行后拼接123 // 遍历所有非 TilingHead 和 TilingData 的条目,去掉第一行后拼接
116 for (const auto &[key, value] : tiling_file_name_to_content) {124 for (const auto &[key, value] : tiling_file_name_to_content) {
117- if (key == kTilingHeadIdentify || key.find(kTilingDataIdentify) != std::string::npos) {125+ if (key == kTilingHeadIdentify || IsSplitTilingHeaderKey(key) ||
126+ key.find(kTilingDataIdentify) != std::string::npos) {
118 continue;127 continue;
119 }128 }
120 129 
121- // 查找并跳过第一行头文件行130+ result += RemoveSplitCppIncludes(value);
122- size_t include_pos = value.find(kTilingHeadInclude);
123- if (include_pos != std::string::npos) {
124- // 找到 include 行,跳过它,并去掉后面的换行符
125- size_t content_start = include_pos + kTilingHeadInclude.length();
126- while (content_start < value.size() && (value[content_start] == '\n' || value[content_start] == '\r')) {
127- content_start++;
128- }
129- result += value.substr(content_start);
130- } else {
131- // 如果没有 include 行,直接拼接整个内容
132- result += value;
133- }
134 131 
135 if (!result.empty() && result.back() != '\n') {132 if (!result.empty() && result.back() != '\n') {
136 result += '\n';133 result += '\n';
@@ -155,24 +152,24 @@ void AppendSplitEnd(const std::string &key, std::string &result) {
155 result += "\n";152 result += "\n";
156}153}
157 154 
158-std::string RemoveSplitCppInclude(const std::string &content, const std::string &include) {
159- size_t include_pos = content.find(include);
160- if (include_pos == std::string::npos) {
161- return content;
162- }
163- if (include_pos != 0U) {
164- GELOGW("Split cpp include [%s] is not at file begin, keep original content.", include.c_str());
165- return content;
166- }
167- size_t content_start = include_pos + include.length();
168- while (content_start < content.size() && (content[content_start] == '\n' || content[content_start] == '\r')) {
169- content_start++;
170- }
171- return content.substr(content_start);
172-}
173- 
174std::string RemoveSplitCppIncludes(const std::string &content) {155std::string RemoveSplitCppIncludes(const std::string &content) {
175- return RemoveSplitCppInclude(RemoveSplitCppInclude(content, kTilingHeadInclude), kCubeKernelTilingWrapperInclude);156+ const std::set<std::string> split_includes = {
157+ kTilingHeadInclude, kTilingStateHeaderInclude, kTilingLogHeaderInclude, kTilingPgoHeaderInclude,
158+ kTilingBaseHeaderInclude, kTilingSolverHeaderInclude, kTilingApiHeaderInclude, kTilingEntryHeaderInclude,
159+ kTilingTailHeaderInclude, kCubeKernelTilingWrapperInclude};
160+ std::istringstream input(content);
161+ std::stringstream output;
162+ std::string line;
163+ bool in_include_prefix = true;
164+ while (std::getline(input, line)) {
165+ if (in_include_prefix && !line.empty() && line.rfind("#include ", 0U) != 0U) {
166+ in_include_prefix = false;
167+ }
168+ if (!in_include_prefix || split_includes.count(line) == 0U) {
169+ output << line << '\n';
170+ }
171+ }
172+ return output.str();
176}173}
177 174 
178void AppendSplitSource(const std::string &key, const std::string &content, std::string &result) {175void AppendSplitSource(const std::string &key, const std::string &content, std::string &result) {
@@ -181,38 +178,53 @@ void AppendSplitSource(const std::string &key, const std::string &content, std::
181 AppendSplitEnd(key, result);178 AppendSplitEnd(key, result);
182}179}
183 180 
184-void AppendLineBreakIfNeeded(std::string &content) {
185- if (!content.empty() && content.back() != '\n') {
186- content += '\n';
187- }
188-}
189- 
190std::string BuildSplitHeaderContent(const std::map<std::string, std::string> &tiling_file_name_to_content) {181std::string BuildSplitHeaderContent(const std::map<std::string, std::string> &tiling_file_name_to_content) {
191- std::string content = RemoveAutoFuseTilingHeadGuards(tiling_file_name_to_content.at(kTilingHeadIdentify));182+ return RemoveAutoFuseTilingHeadGuards(tiling_file_name_to_content.at(kTilingHeadIdentify));
192- auto wrapper_header = tiling_file_name_to_content.find(kCubeKernelTilingWrapperHpp);
193- if (wrapper_header != tiling_file_name_to_content.end()) {
194- AppendLineBreakIfNeeded(content);
195- content += wrapper_header->second;
196- AppendLineBreakIfNeeded(content);
197- }
198- return content;
199}183}
200 184 
201bool ShouldSkipSplitCppSource(const std::string &key) {185bool ShouldSkipSplitCppSource(const std::string &key) {
202- return key == kTilingHeadIdentify || key == kCubeKernelTilingWrapperHpp ||186+ return key == kTilingHeadIdentify || IsSplitTilingHeaderKey(key) || key == kCubeKernelTilingWrapperHpp ||
203 key.find(kTilingDataIdentify) != std::string::npos;187 key.find(kTilingDataIdentify) != std::string::npos;
204}188}
205 189 
190+bool HasNewSplitTilingHeaders(const std::map<std::string, std::string> &tiling_file_name_to_content) {
191+ return tiling_file_name_to_content.find(kTilingStateHeaderIdentify) != tiling_file_name_to_content.end();
192+}
193+ 
194+void AppendSplitHeaderSources(const std::map<std::string, std::string> &tiling_file_name_to_content, bool is_new_format,
195+ std::string &result) {
196+ std::string tiling_head = BuildSplitHeaderContent(tiling_file_name_to_content);
197+ if (!is_new_format) {
198+ auto wrapper_header = tiling_file_name_to_content.find(kCubeKernelTilingWrapperHpp);
199+ if (wrapper_header != tiling_file_name_to_content.end()) {
200+ if (!tiling_head.empty() && tiling_head.back() != '\n') {
201+ tiling_head += '\n';
202+ }
203+ tiling_head += wrapper_header->second;
204+ }
205+ AppendSplitSource(kTilingHeadIdentify, tiling_head, result);
206+ return;
207+ }
208+ for (const auto &key : {kTilingStateHeaderIdentify, kTilingLogHeaderIdentify, kTilingPgoHeaderIdentify,
209+ kTilingSolverHeaderIdentify, kTilingApiHeaderIdentify, kCubeKernelTilingWrapperHpp}) {
210+ auto iter = tiling_file_name_to_content.find(key);
211+ if (iter != tiling_file_name_to_content.end()) {
212+ AppendSplitSource(key, iter->second, result);
213+ }
214+ }
215+}
216+ 
206Status CombineTilingsWithSplitMarkers(const std::map<std::string, std::string> &tiling_file_name_to_content,217Status CombineTilingsWithSplitMarkers(const std::map<std::string, std::string> &tiling_file_name_to_content,
207 std::string &result) {218 std::string &result) {
208 GE_CHK_BOOL_RET_STATUS(tiling_file_name_to_content.find(kTilingHeadIdentify) != tiling_file_name_to_content.end(),219 GE_CHK_BOOL_RET_STATUS(tiling_file_name_to_content.find(kTilingHeadIdentify) != tiling_file_name_to_content.end(),
209 af::FAILED, "tiling_file_name_to_content has no tiling head");220 af::FAILED, "tiling_file_name_to_content has no tiling head");
210- AppendSplitSource(kTilingHeadIdentify, BuildSplitHeaderContent(tiling_file_name_to_content), result);221+ const bool is_new_format = HasNewSplitTilingHeaders(tiling_file_name_to_content);
222+ AppendSplitHeaderSources(tiling_file_name_to_content, is_new_format, result);
211 for (const auto &[key, value] : tiling_file_name_to_content) {223 for (const auto &[key, value] : tiling_file_name_to_content) {
212 if (ShouldSkipSplitCppSource(key)) {224 if (ShouldSkipSplitCppSource(key)) {
213 continue;225 continue;
214 }226 }
215- AppendSplitSource(key, RemoveSplitCppIncludes(value), result);227+ AppendSplitSource(key, is_new_format ? value : RemoveSplitCppIncludes(value), result);
216 }228 }
217 return af::SUCCESS;229 return af::SUCCESS;
218}230}
@@ -12,6 +12,7 @@
12#include "codegen_tiling_data.h"12#include "codegen_tiling_data.h"
13 13 
14#include <algorithm>14#include <algorithm>
15+#include <initializer_list>
15#include <string>16#include <string>
16#include <cstdlib>17#include <cstdlib>
17#include <fstream>18#include <fstream>
@@ -36,6 +37,7 @@
36#include "backend/backend_spec.h"37#include "backend/backend_spec.h"
37#include "common/ascgraph_info_complete.h"38#include "common/ascgraph_info_complete.h"
38#include "codegen_tiling_cube_wrapper.h"39#include "codegen_tiling_cube_wrapper.h"
40+#include "common/tiling_source_dependencies.h"
39 41 
40namespace codegen {42namespace codegen {
41using optimize::AscGraphInfoComplete;43using optimize::AscGraphInfoComplete;
@@ -71,11 +73,225 @@ bool CheckTilingHeadersValid(const std::map<std::string, std::string> &tiling_fi
71 return true;73 return true;
72}74}
73 75 
74-void AppendCommonTilingHeaders(std::stringstream &ss) {76+void RequireSystemHeaders(autofuse::SourceDependencies &dependencies, std::initializer_list<const char *> headers) {
75- ss << kTilingHeadInclude << std::endl;77+ for (const auto *header : headers) {
76- ss << kTilingHeadCceKtTestGuard << std::endl;78+ autofuse::RequireSystemHeader(dependencies, header);
77- ss << kTilingHeadTilingContext << std::endl;79+ }
78- ss << kTilingHeadEndGuard << std::endl;80+}
81+ 
82+void RequireEntrySystemHeaders(autofuse::SourceDependencies &dependencies, bool is_inductor, bool is_cv,
83+ bool is_multi_group) {
84+ if (is_inductor && is_cv) {
85+ RequireSystemHeaders(dependencies, {"algorithm", "cfloat", "cstddef", "cstdint", "cstring", "ostream", "sstream",
86+ "string", "vector"});
87+ } else if (is_inductor) {
88+ RequireSystemHeaders(dependencies, {"algorithm", "cfloat", "cmath", "cstddef", "cstdint", "map", "ostream",
89+ "sstream", "string", "unordered_map", "vector"});
90+ } else {
91+ RequireSystemHeaders(dependencies, {"algorithm", "cfloat", "cmath", "cstddef", "cstdint", "cstdlib", "map",
92+ "ostream", "sstream", "string", "unordered_map", "vector"});
93+ }
94+ if (is_multi_group) {
95+ autofuse::RequireSystemHeader(dependencies, "utility");
96+ }
97+}
98+ 
99+bool ImplGraphHasWorkspace(const ascir::ImplGraph &graph) {
100+ auto nodes = graph.GetAllNodes();
101+ for (const auto &node : nodes) {
102+ if (IsOps<Workspace>(node)) {
103+ return true;
104+ }
105+ }
106+ return false;
107+}
108+ 
109+bool ScheduleGroupHasWorkspace(const ascir::ScheduleGroup &group) {
110+ return std::any_of(group.impl_graphs.begin(), group.impl_graphs.end(), ImplGraphHasWorkspace);
111+}
112+ 
113+bool ScheduledResultHasWorkspace(const ascir::ScheduledResult &result) {
114+ return std::any_of(result.schedule_groups.begin(), result.schedule_groups.end(), ScheduleGroupHasWorkspace);
115+}
116+ 
117+bool EntryWorkspaceUsesSolver(const ascir::FusedScheduledResult &fused_schedule_result) {
118+ for (const auto &scheduled_results : fused_schedule_result.node_idx_to_scheduled_results) {
119+ if (std::any_of(scheduled_results.begin(), scheduled_results.end(), ScheduledResultHasWorkspace)) {
120+ return true;
121+ }
122+ }
123+ return false;
124+}
125+ 
126+struct EntryTranslationUnitOptions {
127+ bool is_inductor;
128+ bool is_cv;
129+ bool include_pgo;
130+ bool enable_pgo_runtime;
131+ bool include_solver;
132+ bool is_multi_group;
133+ bool include_cube_wrapper = false;
134+};
135+ 
136+EntryTranslationUnitOptions GetInductorEntryTranslationUnitOptions(
137+ const ascir::FusedScheduledResult &fused_schedule_result, bool is_cv, bool enable_pgo_runtime) {
138+ return {true,
139+ is_cv,
140+ true,
141+ enable_pgo_runtime,
142+ enable_pgo_runtime || EntryWorkspaceUsesSolver(fused_schedule_result),
143+ !ascgen_utils::IsSingleGroup(fused_schedule_result),
144+ is_cv};
145+}
146+ 
147+std::string RenderEntryTranslationUnit(const std::string &body, const EntryTranslationUnitOptions &options) {
148+ autofuse::GeneratedCode code;
149+ code.body = "using namespace optiling;\n\n" + body;
150+ RequireEntrySystemHeaders(code.dependencies, options.is_inductor, options.is_cv, options.is_multi_group);
151+ autofuse::RequireGeneratedHeader(code.dependencies, autofuse::GeneratedHeaderId::kTilingData);
152+ autofuse::RequireGeneratedHeader(code.dependencies, autofuse::GeneratedHeaderId::kLog);
153+ if (options.include_pgo) {
154+ autofuse::RequireGeneratedHeader(code.dependencies, autofuse::GeneratedHeaderId::kPgo);
155+ }
156+ if (options.enable_pgo_runtime) {
157+ RequireSystemHeaders(code.dependencies, {"fstream", "securec.h", "unordered_set"});
158+ }
159+ if (options.include_solver) {
160+ autofuse::RequireGeneratedHeader(code.dependencies, autofuse::GeneratedHeaderId::kSolver);
161+ }
162+ autofuse::RequireGeneratedHeader(code.dependencies, autofuse::GeneratedHeaderId::kApi);
163+ if (!options.is_inductor) {
164+ autofuse::RequireExternalHeaderUnlessCceKtTest(code.dependencies, "exe_graph/runtime/tiling_context.h");
165+ autofuse::RequireExternalHeaderUnlessCceKtTest(code.dependencies, "tiling/platform/platform_ascendc.h");
166+ }
167+ if (options.is_cv && !options.is_inductor) {
168+ autofuse::RequireExternalHeader(code.dependencies, "autofuse_cube_tiling_data.h");
169+ }
170+ if (options.include_cube_wrapper) {
171+ autofuse::RequireExternalHeader(code.dependencies, "cube_kernel_tiling_wrapper.h");
172+ }
173+ std::string output;
174+ GE_ASSERT_SUCCESS(autofuse::RenderTranslationUnit(code, output));
175+ return output;
176+}
177+ 
178+void AddFallbackHeader(std::map<std::string, std::string> &headers, const std::string &key, const std::string &guard,
179+ autofuse::GeneratedCode code) {
180+ std::string output;
181+ if (autofuse::RenderGeneratedHeader(code, guard, output) != af::SUCCESS) {
182+ return;
183+ }
184+ headers.emplace(key, std::move(output));
185+}
186+ 
187+std::string GetFallbackSolverMacros() {
188+ return "#define Max(a, b) ((double)(a) > (double)(b) ? (a) : (b))\n"
189+ "#define Min(a, b) ((double)(a) < (double)(b) ? (a) : (b))\n"
190+ "#define Abs(a) ((double)(a) >= 0 ? (a) : -(a))\n"
191+ "#define Log(a) (log((double)(a)))\n"
192+ "#define Pow(a, b) pow(a, b)\n"
193+ "#define Rational(a, b) ((double)(a) / (double)(b))\n"
194+ "#define ExpectEq(a, b) ((a) == (b))\n"
195+ "#define ExpectNe(a, b) ((a) != (b))\n"
196+ "#define ExpectLe(a, b) ((a) <= (b))\n"
197+ "#define ExpectLt(a, b) ((a) < (b))\n"
198+ "#define LogicAnd(a, b) ((a) && (b))\n"
199+ "#define LogicOr(a, b) ((a) || (b))\n"
200+ "#define True true\n#define False false\n#define MAX_SOLUTION 50\n";
201+}
202+ 
203+std::string GetFallbackSolverFunctions() {
204+ return R"(namespace optiling {
205+inline bool IsEqual(double a, double b) {
206+ constexpr double kEpsilon = 1e-8;
207+ double abs = (a > b) ? (a - b) : (b - a);
208+ return abs < kEpsilon;
209+}
210+template <typename T1, typename T2>
211+inline double TernaryOp(bool cond, T1 a, T2 b) {
212+ return static_cast<double>(cond ? a : b);
213+}
214+template <typename T>
215+inline T Ceiling(T a) {
216+ T value = static_cast<T>(static_cast<int64_t>(a));
217+ return IsEqual(value, a) ? value : (value + 1);
218+}
219+template <typename T>
220+inline T Floor(T a) {
221+ return static_cast<T>(static_cast<int64_t>(a));
222+}
223+template <typename T1, typename T2>
224+inline auto Mod(T1 a, T2 b) -> decltype(a % b) {
225+ return a % b;
226+}
227+template <typename T1, typename T2>
228+inline auto Mod(T1 a, T2 b) -> typename std::enable_if<std::is_floating_point<T1>::value ||
229+ std::is_floating_point<T2>::value,
230+ decltype(std::fmod(a, b))>::type {
231+ return std::fmod(a, b);
232+}
233+template <typename TI, typename TO>
234+inline TO &RefToRef(TI &value) {
235+ return *(reinterpret_cast<TO *>(reinterpret_cast<void *>(&value)));
236+}
237+} // namespace optiling
238+)";
239+}
240+ 
241+void EnsureFallbackAtomicHeaders(std::map<std::string, std::string> &headers, const std::string &pgo_body,
242+ const std::string &api_body) {
243+ if (headers.find(kTilingStateHeaderIdentify) != headers.end()) {
244+ return;
245+ }
246+ autofuse::GeneratedCode state;
247+ state.body = "namespace optiling {}\n";
248+ AddFallbackHeader(headers, kTilingStateHeaderIdentify, "__AUTOFUSE_TILING_FUNC_STATE_H__", std::move(state));
249+ 
250+ autofuse::GeneratedCode log;
251+ log.body =
252+ "#define OP_LOGD(name, fmt, ...)\n#define OP_LOGI(name, fmt, ...)\n"
253+ "#define OP_LOGW(name, fmt, ...)\n#define OP_LOGE(name, fmt, ...)\n#define OP_NAME \"Autofuse\"\n";
254+ AddFallbackHeader(headers, kTilingLogHeaderIdentify, "__AUTOFUSE_TILING_FUNC_LOG_H__", std::move(log));
255+ 
256+ autofuse::GeneratedCode solver;
257+ for (const auto &header : {"cmath", "cstdint", "type_traits"}) {
258+ autofuse::RequireSystemHeader(solver.dependencies, header);
259+ }
260+ solver.body = GetFallbackSolverMacros() + GetFallbackSolverFunctions();
261+ AddFallbackHeader(headers, kTilingSolverHeaderIdentify, "__AUTOFUSE_TILING_FUNC_SOLVER_H__", std::move(solver));
262+ 
263+ autofuse::GeneratedCode api;
264+ autofuse::RequireSystemHeader(api.dependencies, "cstdint");
265+ if (!pgo_body.empty()) {
266+ autofuse::RequireSystemHeader(api.dependencies, "unordered_map");
267+ autofuse::RequireSystemHeader(api.dependencies, "vector");
268+ }
269+ api.body =
270+ "struct AutofuseTilingData;\nstruct AutofuseTilingDataPerf;\nstruct PgoTensorArgs;\n"
271+ "namespace optiling {\nstruct SearchConfig;\n" +
272+ api_body + "} // namespace optiling\n";
273+ AddFallbackHeader(headers, kTilingApiHeaderIdentify, "__AUTOFUSE_TILING_FUNC_API_H__", std::move(api));
274+ if (!pgo_body.empty()) {
275+ autofuse::GeneratedCode pgo;
276+ for (const auto &header : {"array", "cstddef", "cstdint", "vector"}) {
277+ autofuse::RequireSystemHeader(pgo.dependencies, header);
278+ }
279+ pgo.body = "struct AutofuseTilingData;\nstruct AutofuseTilingDataPerf;\n" + pgo_body;
280+ AddFallbackHeader(headers, kTilingPgoHeaderIdentify, "__AUTOFUSE_TILING_FUNC_PGO_H__", std::move(pgo));
281+ }
282+}
283+ 
284+void AddCvDeclarationsToApiHeader(std::map<std::string, std::string> &headers) {
285+ auto iter = headers.find(kTilingApiHeaderIdentify);
286+ if (iter == headers.end()) {
287+ return;
288+ }
289+ const auto guard_end = iter->second.rfind("#endif");
290+ if (guard_end == std::string::npos) {
291+ return;
292+ }
293+ iter->second.insert(guard_end,
294+ "int32_t get_g_basen_basem_align();\nvoid set_g_basen_basem_align(int32_t value);\n\n");
79}295}
80 296 
81void AppendCvSafetyAivOnlyModeDef(std::stringstream &ss, bool is_batch) {297void AppendCvSafetyAivOnlyModeDef(std::stringstream &ss, bool is_batch) {
@@ -336,14 +552,8 @@ std::map<std::string, std::string> TilingLib::GenerateForInductor(
336 GetTilingHeaders(elemwise_schedule_result, true, is_cube_fused_scheduled);552 GetTilingHeaders(elemwise_schedule_result, true, is_cube_fused_scheduled);
337 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);553 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);
338 std::stringstream ss;554 std::stringstream ss;
339- if (is_cube_fused_scheduled) {
340- AppendCVFusionHeaders(ss, false, true);
341- } else {
342- AppendCommonTilingHeaders(ss);
343- }
344 555 
345- ss << "#pragma GCC diagnostic push\n";556+ ss << "#pragma GCC diagnostic push\n" << "#pragma GCC diagnostic ignored \"-Wreturn-type-c-linkage\"\n";
346- ss << "#pragma GCC diagnostic ignored \"-Wreturn-type-c-linkage\"\n";
347 ss << "extern \"C\" std::string GetTilingDataRepr(const AutofuseTilingData *tiling_data);\n";557 ss << "extern \"C\" std::string GetTilingDataRepr(const AutofuseTilingData *tiling_data);\n";
348 ss << "#pragma GCC diagnostic pop\n";558 ss << "#pragma GCC diagnostic pop\n";
349 ss << TilingFuncDefForInductor(fused_schedule_result, elemwise_schedule_result) << std::endl;559 ss << TilingFuncDefForInductor(fused_schedule_result, elemwise_schedule_result) << std::endl;
@@ -370,9 +580,13 @@ std::map<std::string, std::string> TilingLib::GenerateForInductor(
370 ss << TilingData("Autofuse").GenerateConst(fused_schedule_result) << std::endl;580 ss << TilingData("Autofuse").GenerateConst(fused_schedule_result) << std::endl;
371 if (is_cube_fused_scheduled) {581 if (is_cube_fused_scheduled) {
372 tiling_file_name_to_content[kCubeKernelTilingWrapperHpp] = kCubeKernelTilingWrapperHppValue;582 tiling_file_name_to_content[kCubeKernelTilingWrapperHpp] = kCubeKernelTilingWrapperHppValue;
373- tiling_file_name_to_content[kCubeKernelTilingWrapperCpp] = kCubeKernelTilingWrapperCppValue;583+ tiling_file_name_to_content[kCubeKernelTilingWrapperCpp] = kCubeKernelTilingWrapperInclude;
584+ tiling_file_name_to_content[kCubeKernelTilingWrapperCpp] += kCubeKernelTilingWrapperCppValue;
374 }585 }
375- tiling_file_name_to_content[kTilingDefAndConstIdentify] += ss.str();586+ const std::string entry_body = tiling_file_name_to_content[kTilingDefAndConstIdentify] + ss.str();
587+ const auto entry_options =
588+ GetInductorEntryTranslationUnitOptions(elemwise_schedule_result, is_cube_fused_scheduled, enable_autofuse_pgo_);
589+ tiling_file_name_to_content[kTilingDefAndConstIdentify] = RenderEntryTranslationUnit(entry_body, entry_options);
376 590 
377 return tiling_file_name_to_content;591 return tiling_file_name_to_content;
378}592}
@@ -1896,19 +2110,6 @@ void set_g_basen_basem_align(int32_t value) {
1896 return result;2110 return result;
1897}2111}
1898 2112 
1899-void TilingLib::AppendCVFusionHeaders(std::stringstream &ss, bool is_static, bool is_inductor) const {
1900- ss << kTilingHeadInclude << std::endl;
1901- if (!is_inductor) {
1902- ss << kCubeTilingHeadInclude << std::endl;
1903- if (!is_static) {
1904- ss << kCubeKernelTilingWrapperInclude << std::endl;
1905- }
1906- }
1907- ss << kTilingHeadCceKtTestGuard << std::endl;
1908- ss << kTilingHeadTilingContext << std::endl;
1909- ss << kTilingHeadEndGuard << std::endl;
1910-}
1911- 
1912std::map<std::string, std::string> TilingLib::GenerateCVFusion(const ascir::FusedScheduledResult &fused_schedule_result,2113std::map<std::string, std::string> TilingLib::GenerateCVFusion(const ascir::FusedScheduledResult &fused_schedule_result,
1913 const std::map<std::string, std::string> &shape_info,2114 const std::map<std::string, std::string> &shape_info,
1914 const std::string &pgo_dir,2115 const std::string &pgo_dir,
@@ -1928,8 +2129,6 @@ std::map<std::string, std::string> TilingLib::GenerateCVFusion(const ascir::Fuse
1928 tiling_file_name_to_content = GetTilingHeaders(elemwise_schedule_result, false, true);2129 tiling_file_name_to_content = GetTilingHeaders(elemwise_schedule_result, false, true);
1929 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);2130 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);
1930 2131 
1931- std::stringstream ss;
1932- AppendCVFusionHeaders(ss, is_static);
1933 std::map<std::string, std::string> result;2132 std::map<std::string, std::string> result;
1934 if (is_static) {2133 if (is_static) {
1935 result = GenerateCVFusionStatic(fused_schedule_result, elemwise_schedule_result, shape_info, pgo_dir, core_num);2134 result = GenerateCVFusionStatic(fused_schedule_result, elemwise_schedule_result, shape_info, pgo_dir, core_num);
@@ -1937,7 +2136,17 @@ std::map<std::string, std::string> TilingLib::GenerateCVFusion(const ascir::Fuse
1937 result = GenerateCVFusionDynamic(fused_schedule_result, elemwise_schedule_result, shape_info, pgo_dir, core_num);2136 result = GenerateCVFusionDynamic(fused_schedule_result, elemwise_schedule_result, shape_info, pgo_dir, core_num);
1938 }2137 }
1939 2138 
1940- tiling_file_name_to_content[kTilingDefAndConstIdentify] += ss.str() + result[kTilingDefAndConstIdentify];2139+ const std::string entry_body =
2140+ tiling_file_name_to_content[kTilingDefAndConstIdentify] + result[kTilingDefAndConstIdentify];
2141+ const EntryTranslationUnitOptions entry_options = {
2142+ false,
2143+ true,
2144+ enable_autofuse_pgo_,
2145+ enable_autofuse_pgo_,
2146+ enable_autofuse_pgo_ || EntryWorkspaceUsesSolver(elemwise_schedule_result),
2147+ !ascgen_utils::IsSingleGroup(elemwise_schedule_result),
2148+ !is_static};
2149+ tiling_file_name_to_content[kTilingDefAndConstIdentify] = RenderEntryTranslationUnit(entry_body, entry_options);
1941 if (!is_static) {2150 if (!is_static) {
1942 tiling_file_name_to_content[kCubeKernelTilingWrapperHpp] = result[kCubeKernelTilingWrapperHpp];2151 tiling_file_name_to_content[kCubeKernelTilingWrapperHpp] = result[kCubeKernelTilingWrapperHpp];
1943 tiling_file_name_to_content[kCubeKernelTilingWrapperCpp] = result[kCubeKernelTilingWrapperCpp];2152 tiling_file_name_to_content[kCubeKernelTilingWrapperCpp] = result[kCubeKernelTilingWrapperCpp];
@@ -1956,7 +2165,6 @@ std::map<std::string, std::string> TilingLib::Generate(const ascir::FusedSchedul
1956 std::map<std::string, std::string> tiling_file_name_to_content = GetTilingHeaders(fused_schedule_result, false);2165 std::map<std::string, std::string> tiling_file_name_to_content = GetTilingHeaders(fused_schedule_result, false);
1957 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);2166 GE_CHK_BOOL_RET_STATUS_NOLOG(CheckTilingHeadersValid(tiling_file_name_to_content), tiling_file_name_to_content);
1958 std::stringstream ss;2167 std::stringstream ss;
1959- AppendCommonTilingHeaders(ss);
1960 ss << TilingFuncDef(fused_schedule_result, fused_schedule_result, shape_info, pgo_dir, core_num) << std::endl;2168 ss << TilingFuncDef(fused_schedule_result, fused_schedule_result, shape_info, pgo_dir, core_num) << std::endl;
1961 // 生成GenConstTilingData方法2169 // 生成GenConstTilingData方法
1962 ss << TilingData("Autofuse").GenerateConst(fused_schedule_result, false) << std::endl;2170 ss << TilingData("Autofuse").GenerateConst(fused_schedule_result, false) << std::endl;
@@ -1968,7 +2176,15 @@ std::map<std::string, std::string> TilingLib::Generate(const ascir::FusedSchedul
1968 ss << GenGetTilingKeyKernelTypeForStatic(fused_schedule_result);2176 ss << GenGetTilingKeyKernelTypeForStatic(fused_schedule_result);
1969 }2177 }
1970 ss << "#endif" << std::endl;2178 ss << "#endif" << std::endl;
1971- tiling_file_name_to_content[kTilingDefAndConstIdentify] += ss.str();2179+ const std::string entry_body = tiling_file_name_to_content[kTilingDefAndConstIdentify] + ss.str();
2180+ const EntryTranslationUnitOptions entry_options = {
2181+ false,
2182+ false,
2183+ enable_autofuse_pgo_,
2184+ enable_autofuse_pgo_,
2185+ enable_autofuse_pgo_ || EntryWorkspaceUsesSolver(fused_schedule_result),
2186+ !ascgen_utils::IsSingleGroup(fused_schedule_result)};
2187+ tiling_file_name_to_content[kTilingDefAndConstIdentify] = RenderEntryTranslationUnit(entry_body, entry_options);
1972 2188 
1973 return tiling_file_name_to_content;2189 return tiling_file_name_to_content;
1974}2190}
@@ -2035,6 +2251,36 @@ std::string TilingLib::GetStubTilingHeaders(const ascir::FusedScheduledResult &f
2035 return ss.str();2251 return ss.str();
2036}2252}
2037 2253 
2254+std::string TilingLib::GetStubTilingApi(const ascir::FusedScheduledResult &fused_schedule_result,
2255+ bool include_pgo) const {
2256+ std::stringstream ss;
2257+ ss << "extern \"C\" inline bool GetTiling(AutofuseTilingData &tiling_data, int32_t tiling_case_id = -1, "
2258+ "double *perf = nullptr) {\n";
2259+ ss << " (void)tiling_data; (void)tiling_case_id; (void)perf; return true;\n}\n";
2260+ if (!include_pgo) {
2261+ return ss.str();
2262+ }
2263+ const std::string common_params =
2264+ "std::vector<AutofuseTilingDataPerf> &tiling_data_list, AutofuseTilingData &tiling_data, "
2265+ "int32_t tiling_case_id, AutofuseTilingData *output_tiling_data, " +
2266+ PGOSearchFuncInputOutputCallBackDef(fused_schedule_result) +
2267+ "void *stream, uint32_t workspace_size, double &out_best_perf";
2268+ ss << "inline bool PGOSearchTilingKey(" << common_params
2269+ << ", std::unordered_map<int64_t, uint64_t> &workspace_map, "
2270+ "std::vector<uint32_t *> block_dim_vec = {}, const SearchConfig *search_cfg = nullptr) {\n";
2271+ ss << " (void)tiling_data_list; (void)tiling_data; (void)tiling_case_id; (void)output_tiling_data;\n"
2272+ " (void)tensor_args; (void)stream; (void)workspace_size; (void)out_best_perf; (void)workspace_map;\n"
2273+ " (void)block_dim_vec; (void)search_cfg; return true;\n}\n";
2274+ ss << "inline bool PGOSearchTilingKey(" << common_params << ", const SearchConfig *search_cfg = nullptr) {\n";
2275+ ss << " (void)tiling_data_list; (void)tiling_data; (void)tiling_case_id; (void)output_tiling_data;\n"
2276+ " (void)tensor_args; (void)stream; (void)workspace_size; (void)out_best_perf; (void)search_cfg; return true;\n"
2277+ "}\n";
2278+ ss << "inline bool PGOByCoreNumSearchTilingKey(std::vector<AutofuseTilingData> &tiling_data_list, "
2279+ "AutofuseTilingData *tiling_data, uint32_t max_block_dim = 48) {\n";
2280+ ss << " (void)tiling_data_list; (void)tiling_data; (void)max_block_dim; return true;\n}\n";
2281+ return ss.str();
2282+}
2283+ 
2038std::string TilingLib::GetTilingIncludeHead(bool is_cv) const {2284std::string TilingLib::GetTilingIncludeHead(bool is_cv) const {
2039 std::stringstream ss;2285 std::stringstream ss;
2040 ss << "#ifndef __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;2286 ss << "#ifndef __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;
@@ -2059,6 +2305,25 @@ std::string TilingLib::GetTilingIncludeHead(bool is_cv) const {
2059 return ss.str();2305 return ss.str();
2060}2306}
2061 2307 
2308+void TilingLib::PopulateFallbackAtomicHeaders(std::map<std::string, std::string> &tiling_file_name_to_content,
2309+ const ascir::FusedScheduledResult &fused_schedule_result,
2310+ bool use_att_codegen, bool include_pgo) const {
2311+ std::string fallback_pgo_body;
2312+ std::string fallback_api_body;
2313+ if (!use_att_codegen) {
2314+ fallback_api_body = GetStubTilingApi(fused_schedule_result, include_pgo);
2315+ if (include_pgo) {
2316+ fallback_pgo_body = PGOProfilingCallbackDef(fused_schedule_result, "AutofuseTilingData", false);
2317+ fallback_pgo_body +=
2318+ "namespace optiling {\nstruct SearchConfig {\n"
2319+ " bool ub_threshold_enabled = true;\n double ub_threshold = 0.0;\n"
2320+ " bool corenum_threshold_enabled = true;\n double corenum_threshold = 1.0;\n"
2321+ " bool enable_multicore_ub_tradeoff = true;\n};\n} // namespace optiling\n";
2322+ }
2323+ }
2324+ EnsureFallbackAtomicHeaders(tiling_file_name_to_content, fallback_pgo_body, fallback_api_body);
2325+}
2326+ 
2062std::map<std::string, std::string> TilingLib::GetTilingHeaders(const ascir::FusedScheduledResult &fused_schedule_result,2327std::map<std::string, std::string> TilingLib::GetTilingHeaders(const ascir::FusedScheduledResult &fused_schedule_result,
2063 bool is_inductor_scene, bool is_cv) const {2328 bool is_inductor_scene, bool is_cv) const {
2064 std::stringstream ss;2329 std::stringstream ss;
@@ -2074,13 +2339,18 @@ std::map<std::string, std::string> TilingLib::GetTilingHeaders(const ascir::Fuse
2074 if (ascgen_utils::IsJustCubeFixpip(fused_schedule_result)) {2339 if (ascgen_utils::IsJustCubeFixpip(fused_schedule_result)) {
2075 ss << "#endif // __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;2340 ss << "#endif // __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;
2076 tiling_file_name_to_content[kTilingHeadIdentify] += ss.str();2341 tiling_file_name_to_content[kTilingHeadIdentify] += ss.str();
2342+ EnsureFallbackAtomicHeaders(tiling_file_name_to_content, "", GetStubTilingApi(fused_schedule_result, false));
2343+ if (is_cv) {
2344+ AddCvDeclarationsToApiHeader(tiling_file_name_to_content);
2345+ }
2077 return tiling_file_name_to_content;2346 return tiling_file_name_to_content;
2078 }2347 }
2079 2348 
2080- if (enable_autofuse_pgo_ || is_inductor_scene) {2349+ const bool use_att_codegen = this->codegen_func_ != nullptr && !IsEmptyTensorSence(fused_schedule_result);
2350+ if ((enable_autofuse_pgo_ || is_inductor_scene) && !use_att_codegen) {
2081 ss << PGOProfilingCallbackDef(fused_schedule_result, tiling_name);2351 ss << PGOProfilingCallbackDef(fused_schedule_result, tiling_name);
2082 }2352 }
2083- if (this->codegen_func_ != nullptr && !IsEmptyTensorSence(fused_schedule_result)) {2353+ if (use_att_codegen) {
2084 std::map<std::string, std::string> options;2354 std::map<std::string, std::string> options;
2085 tiling_file_name_to_content[kTilingHeadIdentify] += ss.str();2355 tiling_file_name_to_content[kTilingHeadIdentify] += ss.str();
2086 options.emplace("tiling_data_type_name", tiling_name);2356 options.emplace("tiling_data_type_name", tiling_name);
@@ -2099,7 +2369,11 @@ std::map<std::string, std::string> TilingLib::GetTilingHeaders(const ascir::Fuse
2099 std::stringstream ss_end;2369 std::stringstream ss_end;
2100 ss_end << "#endif // __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;2370 ss_end << "#endif // __AUTOFUSE_TILING_FUNC_COMMON_H__" << std::endl;
2101 tiling_file_name_to_content[kTilingHeadIdentify] += ss_end.str();2371 tiling_file_name_to_content[kTilingHeadIdentify] += ss_end.str();
2102- 2372+ const bool include_pgo = enable_autofuse_pgo_ || is_inductor_scene;
2373+ PopulateFallbackAtomicHeaders(tiling_file_name_to_content, fused_schedule_result, use_att_codegen, include_pgo);
2374+ if (is_cv) {
2375+ AddCvDeclarationsToApiHeader(tiling_file_name_to_content);
2376+ }
2103 return tiling_file_name_to_content;2377 return tiling_file_name_to_content;
2104}2378}
2105 2379 
@@ -3444,23 +3718,7 @@ std::string TilingLib::PGOTensorArgsDef() const {
3444 return ss.str();3718 return ss.str();
3445}3719}
3446 3720 
3447-std::string TilingLib::PGOProfilingCallbackDef(const ascir::FusedScheduledResult &fused_schedule_result,3721+void TilingLib::AppendPgoConfigDef(std::stringstream &ss) const {
3448- const std::string tiling) const {
3449- std::stringstream ss;
3450- 
3451- ss << "#include <cfloat>" << std::endl;
3452- ss << "#include <cstdint>" << std::endl;
3453- ss << "#include <vector>" << std::endl;
3454- ss << "#include <unordered_set>" << std::endl;
3455- ss << "#include <array>" << std::endl;
3456- ss << std::endl;
3457- ss << PGOTensorArgsDef();
3458- ss << "typedef long int (*ProfilingCallback)(";
3459- ss << PGOSearchFuncInputOutputCallBackDef(fused_schedule_result);
3460- ss << "void *stream, uint32_t workspaceSize, " << tiling << " *tiling_data, double *cost_time);" << std::endl;
3461- ss << "typedef long int (*ProfilingBatchCallback)(";
3462- ss << PGOSearchFuncInputOutputCallBackDef(fused_schedule_result);
3463- ss << "void *stream, uint32_t workspaceSize, std::vector<AutofuseTilingDataPerf> *profiles);" << std::endl;
3464 ss << "class PgoConfig {" << std::endl;3722 ss << "class PgoConfig {" << std::endl;
3465 ss << "public:" << std::endl;3723 ss << "public:" << std::endl;
3466 ss << " static PgoConfig& Instance() {" << std::endl;3724 ss << " static PgoConfig& Instance() {" << std::endl;
@@ -3493,6 +3751,28 @@ std::string TilingLib::PGOProfilingCallbackDef(const ascir::FusedScheduledResult
3493 ss << " PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }" << std::endl;3751 ss << " PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }" << std::endl;
3494 ss << " ~PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }" << std::endl;3752 ss << " ~PgoConfigRuntimeGuard() { PgoConfig::Instance().ResetRuntimeOverrides(); }" << std::endl;
3495 ss << "};" << std::endl;3753 ss << "};" << std::endl;
3754+}
3755+ 
3756+std::string TilingLib::PGOProfilingCallbackDef(const ascir::FusedScheduledResult &fused_schedule_result,
3757+ const std::string tiling, bool include_headers) const {
3758+ std::stringstream ss;
3759+ 
3760+ if (include_headers) {
3761+ ss << "#include <cfloat>" << std::endl;
3762+ ss << "#include <cstdint>" << std::endl;
3763+ ss << "#include <vector>" << std::endl;
3764+ ss << "#include <unordered_set>" << std::endl;
3765+ ss << "#include <array>" << std::endl;
3766+ ss << std::endl;
3767+ }
3768+ ss << PGOTensorArgsDef();
3769+ ss << "typedef long int (*ProfilingCallback)(";
3770+ ss << PGOSearchFuncInputOutputCallBackDef(fused_schedule_result);
3771+ ss << "void *stream, uint32_t workspaceSize, " << tiling << " *tiling_data, double *cost_time);" << std::endl;
3772+ ss << "typedef long int (*ProfilingBatchCallback)(";
3773+ ss << PGOSearchFuncInputOutputCallBackDef(fused_schedule_result);
3774+ ss << "void *stream, uint32_t workspaceSize, std::vector<AutofuseTilingDataPerf> *profiles);" << std::endl;
3775+ AppendPgoConfigDef(ss);
3496 ss << std::endl;3776 ss << std::endl;
3497 3777 
3498 return ss.str();3778 return ss.str();
@@ -4454,7 +4734,7 @@ void TilingLib::GenDeduplicateCandidateSolutions(std::stringstream &ss) const {
4454 ss << " continue;" << std::endl;4734 ss << " continue;" << std::endl;
4455 ss << " }" << std::endl;4735 ss << " }" << std::endl;
4456 ss << " auto &kept = deduplicated[iter->second];" << std::endl;4736 ss << " auto &kept = deduplicated[iter->second];" << std::endl;
4457- ss << " if (!IsEqual(kept.modeled_perf, solution.modeled_perf)) {" << std::endl;4737+ ss << " if (!(std::fabs(kept.modeled_perf - solution.modeled_perf) < 1e-8)) {" << std::endl;
4458 ss << " OP_LOGW(OP_NAME, \"same repr with different modeled_perf, keep first: kept=%.6f, current=%.6f, "4738 ss << " OP_LOGW(OP_NAME, \"same repr with different modeled_perf, keep first: kept=%.6f, current=%.6f, "
4459 "repr=%s\", "4739 "repr=%s\", "
4460 << "kept.modeled_perf, solution.modeled_perf, solution.canonical_repr.c_str());" << std::endl;4740 << "kept.modeled_perf, solution.modeled_perf, solution.canonical_repr.c_str());" << std::endl;
@@ -4549,7 +4829,7 @@ std::string TilingLib::GenInductorConfigParserForInductor() const {
4549 ss << " if (ub_it != raw.end()) {" << std::endl;4829 ss << " if (ub_it != raw.end()) {" << std::endl;
4550 ss << " out.ub_threshold_enabled = true;" << std::endl;4830 ss << " out.ub_threshold_enabled = true;" << std::endl;
4551 ss << " try { out.ub_threshold = std::stod(ub_it->second); } catch (...) { return false; }" << std::endl;4831 ss << " try { out.ub_threshold = std::stod(ub_it->second); } catch (...) { return false; }" << std::endl;
4552- ss << " if (IsEqual(out.ub_threshold, 0.0)) { out.ub_threshold = kMinUbThreshold; }" << std::endl;4832+ ss << " if (std::fabs(out.ub_threshold) < 1e-8) { out.ub_threshold = kMinUbThreshold; }" << std::endl;
4553 ss << " }" << std::endl;4833 ss << " }" << std::endl;
4554 ss << " auto cn_it = raw.find(\"corenum_threshold\");" << std::endl;4834 ss << " auto cn_it = raw.find(\"corenum_threshold\");" << std::endl;
4555 ss << " if (cn_it != raw.end()) {" << std::endl;4835 ss << " if (cn_it != raw.end()) {" << std::endl;
@@ -17,12 +17,26 @@
17 17 
18namespace codegen {18namespace codegen {
19const std::string kTilingHeadIdentify = "TilingHead";19const std::string kTilingHeadIdentify = "TilingHead";
20+const std::string kTilingStateHeaderIdentify = "TilingStateHeader";
21+const std::string kTilingLogHeaderIdentify = "TilingLogHeader";
22+const std::string kTilingPgoHeaderIdentify = "TilingPgoHeader";
23+const std::string kTilingBaseHeaderIdentify = "TilingBaseHeader";
24+const std::string kTilingSolverHeaderIdentify = "TilingSolverHeader";
25+const std::string kTilingApiHeaderIdentify = "TilingApiHeader";
26+const std::string kTilingEntryHeaderIdentify = "TilingEntryHeader";
27+const std::string kTilingTailHeaderIdentify = "TilingTailHeader";
20const std::string kTilingDataIdentify = "TilingData";28const std::string kTilingDataIdentify = "TilingData";
21const std::string kTilingHeadGuard = "__AUTOFUSE_TILING_FUNC_COMMON_H__";29const std::string kTilingHeadGuard = "__AUTOFUSE_TILING_FUNC_COMMON_H__";
22const std::string kTilingHeadInclude = "#include \"autofuse_tiling_func_common.h\"";30const std::string kTilingHeadInclude = "#include \"autofuse_tiling_func_common.h\"";
31+const std::string kTilingStateHeaderInclude = "#include \"autofuse_tiling_func_state.h\"";
32+const std::string kTilingLogHeaderInclude = "#include \"autofuse_tiling_func_log.h\"";
33+const std::string kTilingPgoHeaderInclude = "#include \"autofuse_tiling_func_pgo.h\"";
34+const std::string kTilingBaseHeaderInclude = "#include \"autofuse_tiling_func_base.h\"";
35+const std::string kTilingSolverHeaderInclude = "#include \"autofuse_tiling_func_solver.h\"";
36+const std::string kTilingApiHeaderInclude = "#include \"autofuse_tiling_func_api.h\"";
37+const std::string kTilingEntryHeaderInclude = "#include \"autofuse_tiling_func_entry.h\"";
38+const std::string kTilingTailHeaderInclude = "#include \"autofuse_tiling_func_tail.h\"";
23const std::string kTilingHeadCceKtTestGuard = "#ifndef __CCE_KT_TEST__";39const std::string kTilingHeadCceKtTestGuard = "#ifndef __CCE_KT_TEST__";
24-const std::string kTilingHeadEndGuard = "#endif";
25-const std::string kTilingHeadTilingContext = "#include \"exe_graph/runtime/tiling_context.h\"";
26const std::string kTilingDefAndConstIdentify = "tiling_def_and_tiling_const";40const std::string kTilingDefAndConstIdentify = "tiling_def_and_tiling_const";
27const std::string kCubeTilingHeadInclude = "#include \"autofuse_cube_tiling_data.h\"";41const std::string kCubeTilingHeadInclude = "#include \"autofuse_cube_tiling_data.h\"";
28const std::string kCubeKernelTilingWrapperHpp = "ACubeKernelTilingWrapperHpp";42const std::string kCubeKernelTilingWrapperHpp = "ACubeKernelTilingWrapperHpp";
@@ -115,7 +129,8 @@ class TilingLib {
115 const std::string tiling) const;129 const std::string tiling) const;
116 std::string PGOTensorArgsDef() const;130 std::string PGOTensorArgsDef() const;
117 std::string PGOProfilingCallbackDef(const ::ascir::FusedScheduledResult &fused_schedule_result,131 std::string PGOProfilingCallbackDef(const ::ascir::FusedScheduledResult &fused_schedule_result,
118- const std::string tiling) const;132+ const std::string tiling, bool include_headers = true) const;
133+ void AppendPgoConfigDef(std::stringstream &ss) const;
119 std::string PGOSearchFuncInputOutputCallBackDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;134 std::string PGOSearchFuncInputOutputCallBackDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
120 std::string PGOSearchFuncInputOutputDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;135 std::string PGOSearchFuncInputOutputDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
121 std::string PGOSearchFuncInputOutputCall(const ::ascir::FusedScheduledResult &fused_schedule_result) const;136 std::string PGOSearchFuncInputOutputCall(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
@@ -131,6 +146,10 @@ class TilingLib {
131 std::string PGOSearchTensorFreeDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;146 std::string PGOSearchTensorFreeDef(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
132 std::string StubHeadersWithoutCodegenFunc() const;147 std::string StubHeadersWithoutCodegenFunc() const;
133 std::string GetStubTilingHeaders(const ::ascir::FusedScheduledResult &fused_schedule_result) const;148 std::string GetStubTilingHeaders(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
149+ std::string GetStubTilingApi(const ::ascir::FusedScheduledResult &fused_schedule_result, bool include_pgo) const;
150+ void PopulateFallbackAtomicHeaders(std::map<std::string, std::string> &tiling_file_name_to_content,
151+ const ::ascir::FusedScheduledResult &fused_schedule_result, bool use_att_codegen,
152+ bool include_pgo) const;
134 std::string GenGetAutoFuseTilingInput(bool is_inductor_scene) const;153 std::string GenGetAutoFuseTilingInput(bool is_inductor_scene) const;
135 std::string GenGetResLimitStru(void) const;154 std::string GenGetResLimitStru(void) const;
136 bool IsMixKernelTaskType(const ::ascir::FusedScheduledResult &fused_schedule_result) const;155 bool IsMixKernelTaskType(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
@@ -272,7 +291,6 @@ class TilingLib {
272 std::string GenGetTilingKeyKernelTypeForStatic(const ::ascir::FusedScheduledResult &fused_schedule_result) const;291 std::string GenGetTilingKeyKernelTypeForStatic(const ::ascir::FusedScheduledResult &fused_schedule_result) const;
273 std::string GenCVTilingFunc() const;292 std::string GenCVTilingFunc() const;
274 std::string GenTilingDataBlockDimAndWss() const;293 std::string GenTilingDataBlockDimAndWss() const;
275- void AppendCVFusionHeaders(std::stringstream &ss, bool is_static, bool is_inductor = false) const;
276 std::map<std::string, std::string> GenerateCVFusionStatic(294 std::map<std::string, std::string> GenerateCVFusionStatic(
277 const ::ascir::FusedScheduledResult &fused_schedule_result,295 const ::ascir::FusedScheduledResult &fused_schedule_result,
278 const ::ascir::FusedScheduledResult &elemwise_schedule_result,296 const ::ascir::FusedScheduledResult &elemwise_schedule_result,
@@ -24,8 +24,10 @@ inline const std::string kCubeKernelTilingWrapperHppValue = R"(
24#include <stdexcept>24#include <stdexcept>
25#include <cstddef>25#include <cstddef>
26#include <cstring>26#include <cstring>
27+#include <cmath>
27#include <iomanip>28#include <iomanip>
28#include <algorithm>29#include <algorithm>
30+#include <limits>
29#include "acl/acl.h"31#include "acl/acl.h"
30#include "platform/platform_info.h"32#include "platform/platform_info.h"
31 33 
@@ -0,0 +1,158 @@
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 AUTOFUSE_COMMON_TILING_SOURCE_DEPENDENCIES_H_
12+#define AUTOFUSE_COMMON_TILING_SOURCE_DEPENDENCIES_H_
13+ 
14+#include <set>
15+#include <string>
16+#if __has_include("ge_common_af/ge_api_error_codes_af.h")
17+#include "ge_common_af/ge_api_error_codes_af.h"
18+#else
19+#include "ge_common_af/ge_api_error_codes.h"
20+#endif
21+ 
22+namespace autofuse {
23+ 
24+enum class GeneratedHeaderId {
25+ kTilingData,
26+ kState,
27+ kLog,
28+ kPgo,
29+ kSolver,
30+ kApi,
31+};
32+ 
33+struct SourceDependencies {
34+ std::set<std::string> system_headers;
35+ std::set<std::string> external_headers;
36+ std::set<std::string> cce_kt_excluded_external_headers;
37+ std::set<GeneratedHeaderId> generated_headers;
38+};
39+ 
40+struct GeneratedCode {
41+ std::string body;
42+ SourceDependencies dependencies;
43+};
44+ 
45+inline void RequireSystemHeader(SourceDependencies &dependencies, const std::string &header) {
46+ dependencies.system_headers.insert(header);
47+}
48+ 
49+inline void RequireExternalHeader(SourceDependencies &dependencies, const std::string &header) {
50+ dependencies.external_headers.insert(header);
51+}
52+ 
53+inline void RequireExternalHeaderUnlessCceKtTest(SourceDependencies &dependencies, const std::string &header) {
54+ dependencies.cce_kt_excluded_external_headers.insert(header);
55+}
56+ 
57+inline void RequireGeneratedHeader(SourceDependencies &dependencies, GeneratedHeaderId header_id) {
58+ dependencies.generated_headers.insert(header_id);
59+}
60+ 
61+inline void MergeDependencies(SourceDependencies &target, const SourceDependencies &source) {
62+ target.system_headers.insert(source.system_headers.begin(), source.system_headers.end());
63+ target.external_headers.insert(source.external_headers.begin(), source.external_headers.end());
64+ target.cce_kt_excluded_external_headers.insert(source.cce_kt_excluded_external_headers.begin(),
65+ source.cce_kt_excluded_external_headers.end());
66+ target.generated_headers.insert(source.generated_headers.begin(), source.generated_headers.end());
67+}
68+ 
69+inline void AppendGeneratedCode(GeneratedCode &target, const GeneratedCode &source) {
70+ target.body += source.body;
71+ MergeDependencies(target.dependencies, source.dependencies);
72+}
73+ 
74+inline af::Status GetGeneratedHeaderFileName(GeneratedHeaderId header_id, std::string &file_name) {
75+ switch (header_id) {
76+ case GeneratedHeaderId::kTilingData:
77+ file_name = "autofuse_tiling_data.h";
78+ break;
79+ case GeneratedHeaderId::kState:
80+ file_name = "autofuse_tiling_func_state.h";
81+ break;
82+ case GeneratedHeaderId::kLog:
83+ file_name = "autofuse_tiling_func_log.h";
84+ break;
85+ case GeneratedHeaderId::kPgo:
86+ file_name = "autofuse_tiling_func_pgo.h";
87+ break;
88+ case GeneratedHeaderId::kSolver:
89+ file_name = "autofuse_tiling_func_solver.h";
90+ break;
91+ case GeneratedHeaderId::kApi:
92+ file_name = "autofuse_tiling_func_api.h";
93+ break;
94+ default:
95+ return af::FAILED;
96+ }
97+ return af::SUCCESS;
98+}
99+ 
100+inline af::Status RenderIncludes(const SourceDependencies &dependencies, std::string &output) {
101+ output.clear();
102+ for (const auto &header : dependencies.system_headers) {
103+ output += "#include <" + header + ">\n";
104+ }
105+ for (const auto &header : dependencies.external_headers) {
106+ output += "#include \"" + header + "\"\n";
107+ }
108+ for (const auto header_id : dependencies.generated_headers) {
109+ std::string file_name;
110+ if (GetGeneratedHeaderFileName(header_id, file_name) != af::SUCCESS) {
111+ output.clear();
112+ return af::FAILED;
113+ }
114+ output += "#include \"" + file_name + "\"\n";
115+ }
116+ if (!dependencies.cce_kt_excluded_external_headers.empty()) {
117+ output += "#ifndef __CCE_KT_TEST__\n";
118+ for (const auto &header : dependencies.cce_kt_excluded_external_headers) {
119+ output += "#include \"" + header + "\"\n";
120+ }
121+ output += "#endif\n";
122+ }
123+ return af::SUCCESS;
124+}
125+ 
126+inline af::Status RenderTranslationUnit(const GeneratedCode &code, std::string &output) {
127+ std::string includes;
128+ if (RenderIncludes(code.dependencies, includes) != af::SUCCESS) {
129+ return af::FAILED;
130+ }
131+ output = includes;
132+ if (!includes.empty() && !code.body.empty()) {
133+ output += "\n";
134+ }
135+ output += code.body;
136+ return af::SUCCESS;
137+}
138+ 
139+inline af::Status RenderGeneratedHeader(const GeneratedCode &code, const std::string &guard, std::string &output) {
140+ if (!code.dependencies.generated_headers.empty()) {
141+ output.clear();
142+ return af::FAILED;
143+ }
144+ std::string includes;
145+ if (RenderIncludes(code.dependencies, includes) != af::SUCCESS) {
146+ return af::FAILED;
147+ }
148+ output = "#ifndef " + guard + "\n#define " + guard + "\n\n";
149+ if (!includes.empty()) {
150+ output += includes + "\n";
151+ }
152+ output += code.body + "\n#endif // " + guard + "\n";
153+ return af::SUCCESS;
154+}
155+ 
156+} // namespace autofuse
157+ 
158+#endif // AUTOFUSE_COMMON_TILING_SOURCE_DEPENDENCIES_H_
@@ -28,7 +28,7 @@ import tbe.common.utils.log as logger
28# Python3 lib pyautofuse.so28# Python3 lib pyautofuse.so
29from .pyautofuse import Schedule, CodeGen, ascir29from .pyautofuse import Schedule, CodeGen, ascir
30from .ascbc_kernel_compile import ascbc_kernel_compile, camel_to_snake30from .ascbc_kernel_compile import ascbc_kernel_compile, camel_to_snake
31-from .compile_adapter import get_pgo_env_flag, get_pgo_topn31+from .compile_adapter import TILING_HEADER_FILES, get_pgo_env_flag, get_pgo_topn
32from tbe.tikcpp.get_op_tiling import (32from tbe.tikcpp.get_op_tiling import (
33 TilingInfo,33 TilingInfo,
34 _change_param_name_to_name,34 _change_param_name_to_name,
@@ -42,6 +42,10 @@ ASCEND_PATH = os.path.join(PYF_PATH, "..", "..", "..")
42timestamp_list = []42timestamp_list = []
43HOST_TILING_COMPILE_JOBS = 3243HOST_TILING_COMPILE_JOBS = 32
44_HOST_SOURCE_EXTENSIONS = (".cpp", ".h", ".hpp")44_HOST_SOURCE_EXTENSIONS = (".cpp", ".h", ".hpp")
45+TILING_FIXED_CPP_FILES = {
46+ "BCubeKernelTilingWrapperCpp": "cube_kernel_tiling_wrapper.cpp",
47+ "CubeKernelTilingWrapperCpp": "cube_kernel_tiling_wrapper.cpp",
48+}
45_SUPPORTED_CROSS_COMPILE_PREFIXES = {49_SUPPORTED_CROSS_COMPILE_PREFIXES = {
46 ("linux", "aarch64"): "aarch64-linux-gnu-",50 ("linux", "aarch64"): "aarch64-linux-gnu-",
47 ("linux", "x86_64"): "x86_64-linux-gnu-",51 ("linux", "x86_64"): "x86_64-linux-gnu-",
@@ -906,13 +910,14 @@ def _process_tiling_funcs_and_infershape(
906 template_dir = host_build_dir910 template_dir = host_build_dir
907 ret_tiling_func_srcs = template_dict911 ret_tiling_func_srcs = template_dict
908 912 
913+ has_atomic_headers = "TilingStateHeader" in template_dict
909 for key, value in template_dict.items():914 for key, value in template_dict.items():
910- if key == "TilingHead":915+ if key == "TilingHead" and has_atomic_headers:
911- generate_file(template_dir, "autofuse_tiling_func_common.h", value)916+ continue
912- elif key == "CubeKernelTilingWrapperHpp":917+ if key in TILING_HEADER_FILES:
913- generate_file(template_dir, "cube_kernel_tiling_wrapper.h", value)918+ generate_file(template_dir, TILING_HEADER_FILES[key], value)
914- elif key == "CubeKernelTilingWrapperCpp":919+ elif key in TILING_FIXED_CPP_FILES:
915- generate_file(template_dir, "cube_kernel_tiling_wrapper.cpp", value)920+ generate_file(template_dir, TILING_FIXED_CPP_FILES[key], value)
916 elif "TilingData" not in key:921 elif "TilingData" not in key:
917 generate_file(922 generate_file(
918 template_dir, graph_name + "_tiling_func_" + key + ".cpp", value923 template_dir, graph_name + "_tiling_func_" + key + ".cpp", value
@@ -1162,7 +1167,16 @@ def replace_host_files(replace_root, host_build_dir, graph_name):
1162 for header_name in [1167 for header_name in [
1163 "autofuse_tiling_data.h",1168 "autofuse_tiling_data.h",
1164 "autofuse_tiling_func_common.h",1169 "autofuse_tiling_func_common.h",
1170+ "autofuse_tiling_func_state.h",
1171+ "autofuse_tiling_func_log.h",
1172+ "autofuse_tiling_func_pgo.h",
1173+ "autofuse_tiling_func_base.h",
1174+ "autofuse_tiling_func_solver.h",
1175+ "autofuse_tiling_func_api.h",
1176+ "autofuse_tiling_func_entry.h",
1177+ "autofuse_tiling_func_tail.h",
1165 "autofuse_cube_tiling_data.h",1178 "autofuse_cube_tiling_data.h",
1179+ "cube_kernel_tiling_wrapper.h",
1166 ]:1180 ]:
1167 header_path = source_dir / header_name1181 header_path = source_dir / header_name
1168 if header_path.exists():1182 if header_path.exists():
@@ -23,8 +23,27 @@ INDUCTOR_COMPILE_TRACE_LABEL = "InductorCompile"
23SPLIT_BEGIN_PREFIX = "// AUTOFUSE_SPLIT_FILE_BEGIN:"23SPLIT_BEGIN_PREFIX = "// AUTOFUSE_SPLIT_FILE_BEGIN:"
24SPLIT_END_PREFIX = "// AUTOFUSE_SPLIT_FILE_END:"24SPLIT_END_PREFIX = "// AUTOFUSE_SPLIT_FILE_END:"
25SPLIT_HEADER_KEY = "TilingHead"25SPLIT_HEADER_KEY = "TilingHead"
26-SPLIT_HEADER_FILE = "autofuse_tiling_func_common.h"
27SPLIT_HEADER_INCLUDE = '#include "autofuse_tiling_func_common.h"'26SPLIT_HEADER_INCLUDE = '#include "autofuse_tiling_func_common.h"'
27+SPLIT_HEADER_FILES = {
28+ "TilingHead": "autofuse_tiling_func_common.h",
29+ "TilingStateHeader": "autofuse_tiling_func_state.h",
30+ "TilingLogHeader": "autofuse_tiling_func_log.h",
31+ "TilingPgoHeader": "autofuse_tiling_func_pgo.h",
32+ "TilingBaseHeader": "autofuse_tiling_func_base.h",
33+ "TilingSolverHeader": "autofuse_tiling_func_solver.h",
34+ "TilingApiHeader": "autofuse_tiling_func_api.h",
35+ "TilingEntryHeader": "autofuse_tiling_func_entry.h",
36+ "TilingTailHeader": "autofuse_tiling_func_tail.h",
37+ "ACubeKernelTilingWrapperHpp": "cube_kernel_tiling_wrapper.h",
38+}
39+TILING_HEADER_FILES = dict(SPLIT_HEADER_FILES)
40+TILING_HEADER_FILES["CubeKernelTilingWrapperHpp"] = "cube_kernel_tiling_wrapper.h"
41+FINAL_SPLIT_DISCRIMINATOR_KEYS = {"TilingStateHeader"}
42+HISTORICAL_SPLIT_DISCRIMINATOR_KEYS = {
43+ "TilingBaseHeader",
44+ "TilingEntryHeader",
45+ "TilingTailHeader",
46+}
28 47 
29 48 
30def str2bool(v):49def str2bool(v):
@@ -129,25 +148,37 @@ def parse_split_marker(line, prefix):
129 return key148 return key
130 149 
131 150 
132-def finish_split_source(key, lines, header, cpp_sources, seen_keys):151+def finish_split_source(key, lines, headers, cpp_sources, seen_keys):
133 if key in seen_keys:152 if key in seen_keys:
134 raise ascendc_compile.CompileError(153 raise ascendc_compile.CompileError(
135 f"split host source key is duplicated: {key}"154 f"split host source key is duplicated: {key}"
136 )155 )
137 seen_keys.add(key)156 seen_keys.add(key)
138 content = "".join(lines)157 content = "".join(lines)
139- if key == SPLIT_HEADER_KEY:158+ if key in SPLIT_HEADER_FILES:
140- if header is not None:159+ headers[key] = content
141- raise ascendc_compile.CompileError("split host source header is duplicated")160+ return headers, cpp_sources
142- return content, cpp_sources161+ if key.endswith("Header") or key.endswith("Hpp"):
162+ raise ascendc_compile.CompileError(f"unknown split host header key: {key}")
143 cpp_sources.append((key, content))163 cpp_sources.append((key, content))
144- return header, cpp_sources164+ return headers, cpp_sources
165+ 
166+ 
167+def validate_split_sources(headers, cpp_sources):
168+ discriminator_keys = (
169+ FINAL_SPLIT_DISCRIMINATOR_KEYS | HISTORICAL_SPLIT_DISCRIMINATOR_KEYS
170+ )
171+ is_split_format = bool(discriminator_keys & set(headers))
172+ if not is_split_format and SPLIT_HEADER_KEY not in headers:
173+ raise ascendc_compile.CompileError("split host source has no TilingHead")
174+ if not cpp_sources:
175+ raise ascendc_compile.CompileError("split host source has no cpp source")
145 176 
146 177 
147def parse_split_host_sources(host_impl_code):178def parse_split_host_sources(host_impl_code):
148 current_key = None179 current_key = None
149 current_lines = []180 current_lines = []
150- header = None181+ headers = {}
151 cpp_sources = []182 cpp_sources = []
152 seen_keys = set()183 seen_keys = set()
153 for line in host_impl_code.splitlines(keepends=True):184 for line in host_impl_code.splitlines(keepends=True):
@@ -172,8 +203,8 @@ def parse_split_host_sources(host_impl_code):
172 raise ascendc_compile.CompileError(203 raise ascendc_compile.CompileError(
173 f"split host source marker mismatch: begin={current_key}, end={end_key}"204 f"split host source marker mismatch: begin={current_key}, end={end_key}"
174 )205 )
175- header, cpp_sources = finish_split_source(206+ headers, cpp_sources = finish_split_source(
176- current_key, current_lines, header, cpp_sources, seen_keys207+ current_key, current_lines, headers, cpp_sources, seen_keys
177 )208 )
178 current_key = None209 current_key = None
179 current_lines = []210 current_lines = []
@@ -189,11 +220,8 @@ def parse_split_host_sources(host_impl_code):
189 raise ascendc_compile.CompileError(220 raise ascendc_compile.CompileError(
190 f"split host source marker is not closed: {current_key}"221 f"split host source marker is not closed: {current_key}"
191 )222 )
192- if header is None:223+ validate_split_sources(headers, cpp_sources)
193- raise ascendc_compile.CompileError("split host source has no TilingHead")224+ return headers, cpp_sources
194- if not cpp_sources:
195- raise ascendc_compile.CompileError("split host source has no cpp source")
196- return header, cpp_sources
197 225 
198 226 
199def add_split_header_include(cpp_content):227def add_split_header_include(cpp_content):
@@ -203,12 +231,20 @@ def add_split_header_include(cpp_content):
203 231 
204 232 
205def write_split_host_sources(host_file_path, graph_name, host_impl_code):233def write_split_host_sources(host_file_path, graph_name, host_impl_code):
206- header, cpp_sources = parse_split_host_sources(host_impl_code)234+ headers, cpp_sources = parse_split_host_sources(host_impl_code)
207- generate_file(host_file_path, SPLIT_HEADER_FILE, header)235+ is_split_format = bool(
236+ (FINAL_SPLIT_DISCRIMINATOR_KEYS | HISTORICAL_SPLIT_DISCRIMINATOR_KEYS)
237+ & set(headers)
238+ )
239+ for key, content in headers.items():
240+ generate_file(host_file_path, SPLIT_HEADER_FILES[key], content)
208 host_files = []241 host_files = []
209 for key, cpp_content in cpp_sources:242 for key, cpp_content in cpp_sources:
210 file_name = f"{graph_name}_tiling_func_{key}.cpp"243 file_name = f"{graph_name}_tiling_func_{key}.cpp"
211- generate_file(host_file_path, file_name, add_split_header_include(cpp_content))244+ content = (
245+ cpp_content if is_split_format else add_split_header_include(cpp_content)
246+ )
247+ generate_file(host_file_path, file_name, content)
212 host_files.append(os.path.join(host_file_path, file_name))248 host_files.append(os.path.join(host_file_path, file_name))
213 return host_files249 return host_files
214 250 
@@ -0,0 +1,103 @@
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 AUTOFUSE_TESTS_COMMON_ATT_COMMON_GEN_UTILS_H_
12+#define AUTOFUSE_TESTS_COMMON_ATT_COMMON_GEN_UTILS_H_
13+ 
14+#include <fstream>
15+#include <map>
16+#include <set>
17+#include <sstream>
18+#include <string>
19+ 
20+namespace att {
21+namespace test {
22+ 
23+inline std::string RemoveAutoFuseTilingHeadGuards(const std::string &input) {
24+ std::istringstream iss(input);
25+ std::ostringstream oss;
26+ std::string line;
27+ const std::string guard_token = "__AUTOFUSE_TILING_FUNC_COMMON_H__";
28+ while (std::getline(iss, line)) {
29+ if (line.find(guard_token) == std::string::npos) {
30+ oss << line << "\n";
31+ }
32+ }
33+ return oss.str();
34+}
35+ 
36+inline bool IsSplitHeaderKey(const std::string &key) {
37+ return key == "TilingStateHeader" || key == "TilingLogHeader" || key == "TilingPgoHeader" ||
38+ key == "TilingSolverHeader" || key == "TilingApiHeader" || key == "TilingBaseHeader" ||
39+ key == "TilingEntryHeader" || key == "TilingTailHeader";
40+}
41+ 
42+inline std::string RemoveSplitIncludes(const std::string &value) {
43+ const std::set<std::string> split_includes = {
44+ "#include \"autofuse_tiling_func_common.h\"", "#include \"autofuse_tiling_func_base.h\"",
45+ "#include \"autofuse_tiling_func_state.h\"", "#include \"autofuse_tiling_func_log.h\"",
46+ "#include \"autofuse_tiling_func_pgo.h\"", "#include \"autofuse_tiling_func_api.h\"",
47+ "#include \"autofuse_tiling_func_solver.h\"", "#include \"autofuse_tiling_func_entry.h\"",
48+ "#include \"autofuse_tiling_func_tail.h\"", "#include \"autofuse_tiling_data.h\""};
49+ std::istringstream input(value);
50+ std::ostringstream output;
51+ std::string line;
52+ bool in_include_prefix = true;
53+ while (std::getline(input, line)) {
54+ if (!in_include_prefix) {
55+ output << line << '\n';
56+ continue;
57+ }
58+ if (split_includes.count(line) != 0U) {
59+ continue;
60+ }
61+ in_include_prefix = line.empty() || line.rfind("#include ", 0U) == 0U;
62+ output << line << '\n';
63+ }
64+ return output.str();
65+}
66+ 
67+inline void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) {
68+ const std::string tiling_head = "TilingHead";
69+ const std::string tiling_data = "TilingData";
70+ result += RemoveAutoFuseTilingHeadGuards(tilings.at(tiling_head));
71+ for (const auto &[key, value] : tilings) {
72+ if (key == tiling_head || IsSplitHeaderKey(key) || key.find(tiling_data) != std::string::npos) {
73+ continue;
74+ }
75+ result += RemoveSplitIncludes(value);
76+ if (!result.empty() && result.back() != '\n') {
77+ result += '\n';
78+ }
79+ }
80+}
81+ 
82+inline void AddHeaderGuardToFile(const std::string &file_name, const std::string &macro_name) {
83+ std::string content;
84+ std::ifstream in_file(file_name);
85+ if (in_file.is_open()) {
86+ std::string line;
87+ while (std::getline(in_file, line)) {
88+ content += line + "\n";
89+ }
90+ in_file.close();
91+ }
92+ std::ofstream out_file(file_name, std::ios::out);
93+ out_file << "#ifndef " << macro_name << "\n";
94+ out_file << "#define " << macro_name << "\n\n";
95+ out_file << content << "\n";
96+ out_file << "#endif // " << macro_name << "\n";
97+ out_file.close();
98+}
99+ 
100+} // namespace test
101+} // namespace att
102+ 
103+#endif // AUTOFUSE_TESTS_COMMON_ATT_COMMON_GEN_UTILS_H_
@@ -8,6 +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#include <iostream>10#include <iostream>
11+#include <vector>
11#include "gtest/gtest.h"12#include "gtest/gtest.h"
12#include "base/att_const_values.h"13#include "base/att_const_values.h"
13#include "gen_model_info.h"14#include "gen_model_info.h"
@@ -19,6 +20,7 @@
19#include "graph_construct_utils.h"20#include "graph_construct_utils.h"
20#include "result_checker_utils.h"21#include "result_checker_utils.h"
21#include "common/st_scenario_utils.h"22#include "common/st_scenario_utils.h"
23+#include "common_gen_utils.h"
22#include "test_common_utils.h"24#include "test_common_utils.h"
23 25 
24using namespace ge::ascir_op;26using namespace ge::ascir_op;
@@ -39,9 +41,9 @@ void Add_Layer_Norm_Slice_AfterQueBufAlloc(ascir::HintGraph &graph);
39void Add_Layer_Norm_Welford_BeforeAutofuse(ascir::HintGraph &graph);41void Add_Layer_Norm_Welford_BeforeAutofuse(ascir::HintGraph &graph);
40void Add_Layer_Norm_Welford_AfterScheduler(ascir::HintGraph &graph);42void Add_Layer_Norm_Welford_AfterScheduler(ascir::HintGraph &graph);
41void Add_Layer_Norm_Welford_AfterQueBufAlloc(ascir::HintGraph &graph);43void Add_Layer_Norm_Welford_AfterQueBufAlloc(ascir::HintGraph &graph);
42-void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result);
43 44 
44using namespace att;45using namespace att;
46+using att::test::CombineTilings;
45 47 
46namespace {48namespace {
47void SetStatsEnv() {49void SetStatsEnv() {
@@ -92,6 +94,26 @@ void WriteTilingFiles(const std::map<std::string, std::string> &tiling_funcs, co
92 WriteFile(head_file, head_include + value);94 WriteFile(head_file, head_include + value);
93 continue;95 continue;
94 }96 }
97+ if (key == "TilingStateHeader") {
98+ WriteFile("autofuse_tiling_func_state.h", value);
99+ continue;
100+ }
101+ if (key == "TilingLogHeader") {
102+ WriteFile("autofuse_tiling_func_log.h", value);
103+ continue;
104+ }
105+ if (key == "TilingPgoHeader") {
106+ WriteFile("autofuse_tiling_func_pgo.h", value);
107+ continue;
108+ }
109+ if (key == "TilingSolverHeader") {
110+ WriteFile("autofuse_tiling_func_solver.h", value);
111+ continue;
112+ }
113+ if (key == "TilingApiHeader") {
114+ WriteFile("autofuse_tiling_func_api.h", value);
115+ continue;
116+ }
95 WriteFile(source_prefix + key + "_3.cpp", value);117 WriteFile(source_prefix + key + "_3.cpp", value);
96 }118 }
97}119}
@@ -217,54 +239,6 @@ TEST_F(TestGenAddLayerNormalModelInfoV2, test_autofuse_v2_axes_reorder) {
217 "tiling_func_main_add_layer_norm_autofuse -I ./",239 "tiling_func_main_add_layer_norm_autofuse -I ./",
218 "./tiling_func_main_add_layer_norm_autofuse");240 "./tiling_func_main_add_layer_norm_autofuse");
219}241}
220-std::string RemoveAutoFuseTilingHeadGuards(const std::string &input) {
221- std::istringstream iss(input);
222- std::ostringstream oss;
223- std::string line;
224- const std::string guard_token = "__AUTOFUSE_TILING_FUNC_COMMON_H__";
225- 
226- while (std::getline(iss, line)) {
227- // 如果当前行不包含 guard_token,则保留
228- if (line.find(guard_token) == std::string::npos) {
229- oss << line << "\n";
230- }
231- }
232- 
233- return oss.str();
234-}
235- 
236-void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) {
237- const std::string tiling_head = "TilingHead"; // TilingHead作为开头拼接其他文件
238- const std::string tiling_data = "TilingData"; // 要排除的 TilingData 子串
239- result += RemoveAutoFuseTilingHeadGuards(tilings.at(tiling_head)); // 删除头文件的宏保护,cpp文件不需要
240- const std::string include_str = "#include \"autofuse_tiling_func_common.h\"";
241- 
242- // 遍历所有非 TilingHead 和 TilingData 的条目,去掉第一行后拼接
243- for (const auto &[key, value] : tilings) {
244- if (key == tiling_head || key.find(tiling_data) != std::string::npos) {
245- continue;
246- }
247- 
248- // 查找并跳过第一行头文件行
249- size_t include_pos = value.find(include_str);
250- if (include_pos != std::string::npos) {
251- // 找到 include 行,跳过它,并去掉后面的换行符
252- size_t content_start = include_pos + include_str.length();
253- while (content_start < value.size() && (value[content_start] == '\n' || value[content_start] == '\r')) {
254- content_start++;
255- }
256- result += value.substr(content_start);
257- } else {
258- // 如果没有 include 行,直接拼接整个内容
259- result += value;
260- }
261- 
262- if (!result.empty() && result.back() != '\n') {
263- result += '\n';
264- }
265- }
266-}
267- 
268const std::string kGroupParallelTilingMain = R"(242const std::string kGroupParallelTilingMain = R"(
269 #include <iostream>243 #include <iostream>
270 #include "AddLayerNorm_tiling_data.h"244 #include "AddLayerNorm_tiling_data.h"
@@ -11,6 +11,7 @@
11#include "common_gen_utils.h"11#include "common_gen_utils.h"
12#include <iostream>12#include <iostream>
13#include <regex>13#include <regex>
14+#include <vector>
14#include "gtest/gtest.h"15#include "gtest/gtest.h"
15#include "base/att_const_values.h"16#include "base/att_const_values.h"
16#include "tiling_code_generator.h"17#include "tiling_code_generator.h"
@@ -447,51 +448,8 @@ Status BuildMatMulDemoAscendGraph(ge::AscGraph &graph) {
447 mat_mul->attr.api.unit = ComputeUnit::kUnitVector;448 mat_mul->attr.api.unit = ComputeUnit::kUnitVector;
448 return af::SUCCESS;449 return af::SUCCESS;
449}450}
450-std::string RemoveAutoFuseTilingHeadGuards(const std::string &input) {
451- std::istringstream iss(input);
452- std::ostringstream oss;
453- std::string line;
454- const std::string guard_token = "__AUTOFUSE_TILING_FUNC_COMMON_H__";
455- 
456- while (std::getline(iss, line)) {
457- // 如果当前行不包含 guard_token,则保留
458- if (line.find(guard_token) == std::string::npos) {
459- oss << line << "\n";
460- }
461- }
462- return oss.str();
463-}
464- 
465void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) {451void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) {
466- const std::string tiling_head = "TilingHead"; // TilingHead作为开头拼接其他文件452+ att::test::CombineTilings(tilings, result);
467- const std::string tiling_data = "TilingData"; // 要排除的 TilingData 子串
468- result += RemoveAutoFuseTilingHeadGuards(tilings.at(tiling_head)); // 删除头文件的宏保护,cpp文件不需要
469- const std::string include_str = "#include \"autofuse_tiling_func_common.h\"";
470- 
471- // 遍历所有非 TilingHead 和 TilingData 的条目,去掉第一行后拼接
472- for (const auto &[key, value] : tilings) {
473- if (key == tiling_head || key.find(tiling_data) != std::string::npos) {
474- continue;
475- }
476- 
477- // 查找并跳过第一行头文件行
478- size_t include_pos = value.find(include_str);
479- if (include_pos != std::string::npos) {
480- // 找到 include 行,跳过它,并去掉后面的换行符
481- size_t content_start = include_pos + include_str.length();
482- while (content_start < value.size() && (value[content_start] == '\n' || value[content_start] == '\r')) {
483- content_start++;
484- }
485- result += value.substr(content_start);
486- } else {
487- // 如果没有 include 行,直接拼接整个内容
488- result += value;
489- }
490- 
491- if (!result.empty() && result.back() != '\n') {
492- result += '\n';
493- }
494- }
495}453}
496} // namespace cg454} // namespace cg
497} // namespace ascir455} // namespace ascir
@@ -1161,7 +1119,7 @@ TEST_F(TestApiTilingGen, gen_mat_mul_tiling_success) {
1161 * - `constexpr size_t kInputShapeSize`1119 * - `constexpr size_t kInputShapeSize`
1162 * - `constexpr size_t kOperatorCacheCapacity`1120 * - `constexpr size_t kOperatorCacheCapacity`
1163 * - `bool FindOperatorCache`1121 * - `bool FindOperatorCache`
1164- * - `bool SaveOperatorCache`1122+ * - `OperatorCacheSaveResult SaveOperatorCache`
1165 * - `bool IsCacheEnabled`1123 * - `bool IsCacheEnabled`
1166 *1124 *
1167 * 备注:验证编译时缓存开关功能正常1125 * 备注:验证编译时缓存开关功能正常
@@ -1204,7 +1162,7 @@ TEST_F(TestApiTilingGen, gen_op_level_cache_basic) {
1204 1162 
1205 // 验证缓存函数生成1163 // 验证缓存函数生成
1206 EXPECT_NE(tiling_func.find("FindOperatorCache(const"), std::string::npos);1164 EXPECT_NE(tiling_func.find("FindOperatorCache(const"), std::string::npos);
1207- EXPECT_NE(tiling_func.find("bool SaveOperatorCache"), std::string::npos);1165+ EXPECT_NE(tiling_func.find("OperatorCacheSaveResult SaveOperatorCache"), std::string::npos);
1208 1166 
1209 // 注意:缓存查询代码(input_shapes数组构建)只在有缓存复用信息时生成1167 // 注意:缓存查询代码(input_shapes数组构建)只在有缓存复用信息时生成
1210 // 这是当前设计的限制,算子级缓存类型和函数已正确生成1168 // 这是当前设计的限制,算子级缓存类型和函数已正确生成
@@ -1339,7 +1297,7 @@ TEST_F(TestApiTilingGen, two_level_cache_full_test) {
1339 1297 
1340 // 验证两级缓存函数生成1298 // 验证两级缓存函数生成
1341 EXPECT_NE(tiling_func.find("FindOperatorCache(const"), std::string::npos);1299 EXPECT_NE(tiling_func.find("FindOperatorCache(const"), std::string::npos);
1342- EXPECT_NE(tiling_func.find("bool SaveOperatorCache"), std::string::npos);1300+ EXPECT_NE(tiling_func.find("OperatorCacheSaveResult SaveOperatorCache"), std::string::npos);
1343 1301 
1344 // 验证TilingCacheContext类生成1302 // 验证TilingCacheContext类生成
1345 EXPECT_NE(tiling_func.find("class TilingCacheContext"), std::string::npos);1303 EXPECT_NE(tiling_func.find("class TilingCacheContext"), std::string::npos);
@@ -9,82 +9,3 @@
9 */9 */
10 10 
11#include "common_gen_utils.h"11#include "common_gen_utils.h"
12-#include <sstream>
13-#include <fstream>
14-#include <algorithm>
15- 
16-namespace att {
17-namespace test {
18- 
19-std::string RemoveAutoFuseTilingHeadGuards(const std::string &input) {
20- std::istringstream iss(input);
21- std::ostringstream oss;
22- std::string line;
23- const std::string guard_token = "__AUTOFUSE_TILING_FUNC_COMMON_H__";
24- 
25- while (std::getline(iss, line)) {
26- // 如果当前行不包含 guard_token,则保留
27- if (line.find(guard_token) == std::string::npos) {
28- oss << line << "\n";
29- }
30- }
31- 
32- return oss.str();
33-}
34- 
35-void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) {
36- const std::string tiling_head = "TilingHead"; // TilingHead作为开头拼接其他文件
37- const std::string tiling_data = "TilingData"; // 要排除的 TilingData 子串
38- result += RemoveAutoFuseTilingHeadGuards(tilings.at(tiling_head)); // 删除头文件的宏保护,cpp文件不需要
39- const std::string include_str = "#include \"autofuse_tiling_func_common.h\"";
40- 
41- // 遍历所有非 TilingHead 和 TilingData 的条目,去掉第一行后拼接
42- for (const auto &[key, value] : tilings) {
43- if (key == tiling_head || key.find(tiling_data) != std::string::npos) {
44- continue;
45- }
46- 
47- // 查找并跳过第一行头文件行
48- size_t include_pos = value.find(include_str);
49- if (include_pos != std::string::npos) {
50- // 找到 include 行,跳过它,并去掉后面的换行符
51- size_t content_start = include_pos + include_str.length();
52- while (content_start < value.size() && (value[content_start] == '\n' || value[content_start] == '\r')) {
53- content_start++;
54- }
55- result += value.substr(content_start);
56- } else {
57- // 如果没有 include 行,直接拼接整个内容
58- result += value;
59- }
60- 
61- if (!result.empty() && result.back() != '\n') {
62- result += '\n';
63- }
64- }
65-}
66- 
67-void AddHeaderGuardToFile(const std::string &file_name, const std::string &macro_name) {
68- std::string content;
69- std::ifstream in_file(file_name);
70- if (in_file.is_open()) {
71- std::string line;
72- while (std::getline(in_file, line)) {
73- content += line + "\n";
74- }
75- in_file.close();
76- }
77- 
78- std::ofstream out_file;
79- out_file.open(file_name, std::ios::out);
80- out_file << "#ifndef " << macro_name << "\n";
81- out_file << "#define " << macro_name << "\n";
82- out_file << "\n";
83- out_file << content;
84- out_file << "\n";
85- out_file << "#endif // " << macro_name << "\n";
86- out_file.close();
87-}
88- 
89-} // namespace test
90-} // namespace att
@@ -11,23 +11,6 @@
11#ifndef TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_11#ifndef TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_
12#define TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_12#define TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_
13 13 
14-#include <string>14+#include "../../../common/att/common_gen_utils.h"
15-#include <map>
16-#include "base/base_types.h"
17- 
18-namespace att {
19-namespace test {
20- 
21-// 拼接tiling函数(参考test_concat.cpp和test_add_layer_norm.cpp)
22-void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result);
23- 
24-// 移除AutoFuse tiling head的宏保护
25-std::string RemoveAutoFuseTilingHeadGuards(const std::string &input);
26- 
27-// 为文件添加头文件宏保护
28-void AddHeaderGuardToFile(const std::string &file_name, const std::string &macro_name);
29- 
30-} // namespace test
31-} // namespace att
32 15 
33#endif // TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_16#endif // TESTS_AUTOFUSE_ST_ATT_UTILS_COMMON_GEN_UTILS_H_
@@ -14,13 +14,225 @@
14#include <dlfcn.h>14#include <dlfcn.h>
15#include <gtest/gtest.h>15#include <gtest/gtest.h>
16 16 
17+#include <cstdio>
18+#include <cstdint>
17#include <fstream>19#include <fstream>
18#include <functional>20#include <functional>
19#include <future>21#include <future>
22+#include <cstdlib>
23+#include <sstream>
20#include <string>24#include <string>
25+#include <sys/wait.h>
26+ 
27+#include "inductor_split_compile_config.h"
21 28 
22namespace autofuse::tests {29namespace autofuse::tests {
23 30 
31+inline std::string ReadFile(const std::string &path) {
32+ std::ifstream in(path);
33+ std::stringstream buf;
34+ buf << in.rdbuf();
35+ return buf.str();
36+}
37+ 
38+inline bool WriteFile(const std::string &path, const std::string &content) {
39+ std::ofstream out(path);
40+ if (!out.is_open()) return false;
41+ out << content;
42+ return true;
43+}
44+ 
45+inline int RunCommand(const std::string &cmd) {
46+ int status = std::system(cmd.c_str());
47+ if (WIFEXITED(status)) return WEXITSTATUS(status);
48+ return -1;
49+}
50+ 
51+inline bool FileExists(const std::string &path) {
52+ std::ifstream f(path);
53+ return f.good();
54+}
55+ 
56+inline bool HasCxx11AbiSymbols(const std::string &path) {
57+ return RunCommand("nm -D " + path + " 2>/dev/null | c++filt | grep -q 'std::__cxx11'") == 0;
58+}
59+ 
60+inline std::string PythonPreamble(const std::string &pyautofuse_dir, const std::string &autofuse_python_dir,
61+ const std::string &ascend_home_path) {
62+ return "import sys, os, traceback\n"
63+ "pkg_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'autofuse_pkg')\n"
64+ "os.makedirs(pkg_dir, exist_ok=True)\n"
65+ "autofuse_dir = os.path.join(pkg_dir, 'autofuse')\n"
66+ "if os.path.islink(autofuse_dir) or os.path.isfile(autofuse_dir):\n"
67+ " os.unlink(autofuse_dir)\n"
68+ "os.makedirs(autofuse_dir, exist_ok=True)\n"
69+ "for name in os.listdir('" +
70+ autofuse_python_dir +
71+ "'):\n"
72+ " src = os.path.join('" +
73+ autofuse_python_dir +
74+ "', name)\n"
75+ " dst = os.path.join(autofuse_dir, name)\n"
76+ " if not os.path.lexists(dst):\n"
77+ " os.symlink(src, dst)\n"
78+ "pyautofuse_src = os.path.join('" +
79+ pyautofuse_dir +
80+ "', 'pyautofuse.so')\n"
81+ "if not os.path.exists(pyautofuse_src):\n"
82+ " raise FileNotFoundError(pyautofuse_src)\n"
83+ "pyautofuse_dst = os.path.join(autofuse_dir, 'pyautofuse.so')\n"
84+ "if os.path.lexists(pyautofuse_dst):\n"
85+ " os.unlink(pyautofuse_dst)\n"
86+ "os.symlink(pyautofuse_src, pyautofuse_dst)\n"
87+ "sys.path.insert(0, pkg_dir)\n"
88+ "import autofuse.ascendc_compile as _ac\n"
89+ "_ac.ASCEND_PATH = '" +
90+ ascend_home_path + "'\n";
91+}
92+ 
93+inline std::string PythonPreamble() {
94+ return PythonPreamble(PYAUTOFUSE_DIR, AUTOFUSE_PYTHON_DIR, ASCEND_HOME_PATH);
95+}
96+ 
97+inline std::string HostCompileScript(const std::string &graph_name, const std::string &output_file,
98+ const std::string &output_dir, const std::string &compile_options,
99+ const std::string &extra_body = "") {
100+ const std::string compile_options_arg = compile_options.empty() ? " '--soc_version=Ascend910B'])\n"
101+ : " '--soc_version=Ascend910B',\n"
102+ " '--compile_options=" +
103+ compile_options + "'])\n";
104+ return "try:\n"
105+ " from autofuse.compile_adapter import host_compile\n"
106+ " import os\n"
107+ " os.makedirs('" +
108+ output_dir +
109+ "/host_out', exist_ok=True)\n"
110+ " td = open('" +
111+ output_dir +
112+ "/host_tiling_def.h').read()\n"
113+ " hc = open('" +
114+ output_dir +
115+ "/host_impl.cpp').read()\n"
116+ " host_compile(td, hc, [\n"
117+ " '--graph_name=" +
118+ graph_name +
119+ "',\n"
120+ " '--output_file=" +
121+ output_file +
122+ "',\n"
123+ " '--output_path=" +
124+ output_dir + "/host_out',\n" + compile_options_arg + extra_body +
125+ "except Exception:\n"
126+ " traceback.print_exc()\n"
127+ " sys.exit(1)\n";
128+}
129+ 
130+inline std::string KernelCompileScript(const std::string &graph_name, const std::string &output_file,
131+ const std::string &work_dir, const std::string &repr_arg) {
132+ return "try:\n"
133+ " from autofuse.compile_adapter import kernel_compile\n"
134+ " import os\n"
135+ " os.makedirs('" +
136+ work_dir +
137+ "', exist_ok=True)\n"
138+ " td = open('" +
139+ work_dir +
140+ "/device_tiling_def.h').read()\n"
141+ " dc = open('" +
142+ work_dir +
143+ "/device_impl.cpp').read()\n"
144+ " argv = ['--graph_name=" +
145+ graph_name +
146+ "',\n"
147+ " '--output_file=" +
148+ output_file +
149+ "',\n"
150+ " '--output_path=" +
151+ work_dir +
152+ "',\n"
153+ " '--soc_version=Ascend910B',\n"
154+ " '--compile_options=-D_GLIBCXX_USE_CXX11_ABI=0']\n"
155+ " kernel_compile(td, dc, argv" +
156+ repr_arg +
157+ ")\n"
158+ "except Exception:\n"
159+ " traceback.print_exc()\n"
160+ " sys.exit(1)\n";
161+}
162+ 
163+inline int RunPythonScript(const std::string &script_path, const std::string &script,
164+ const std::string &ascend_home_path, const std::string &stage) {
165+ WriteFile(script_path, script);
166+ const std::string cmd = "ASCEND_HOME_PATH=" + ascend_home_path + " python3 " + script_path + " 2>&1";
167+ const int ret = RunCommand(cmd);
168+ if (ret != 0) {
169+ std::printf("%s failed, ret=%d\n", stage.c_str(), ret);
170+ }
171+ return ret;
172+}
173+ 
174+inline int RunHostCompile(const std::string &tiling_def, const std::string &host_code, const std::string &output_file,
175+ const std::string &graph_name, const std::string &compile_options) {
176+ WriteFile(std::string(OUTPUT_DIR) + "/host_tiling_def.h", tiling_def);
177+ WriteFile(std::string(OUTPUT_DIR) + "/host_impl.cpp", host_code);
178+ const std::string script_path = std::string(OUTPUT_DIR) + "/run_host_compile.py";
179+ return RunPythonScript(script_path,
180+ PythonPreamble() + HostCompileScript(graph_name, output_file, OUTPUT_DIR, compile_options),
181+ ASCEND_HOME_PATH, "host_compile");
182+}
183+ 
184+struct HostHelperOptions {
185+ std::string input_configs_json = HOST_INPUT_CONFIGS_JSON;
186+ int64_t topn = HOST_TOPN;
187+ std::string perf_order = HOST_PERF_ORDER;
188+ bool check_z0t_positive = false;
189+};
190+ 
191+inline int RunHostHelper(const std::string &host_bin, const std::string &tiling_repr_file,
192+ const HostHelperOptions &options = {}) {
193+ const std::string input_configs_file = std::string(OUTPUT_DIR) + "/host_input_configs.json";
194+ WriteFile(input_configs_file, options.input_configs_json);
195+ std::string cmd = std::string(HOST_HELPER_BIN) + " --host-so " + host_bin + " --tiling-repr-out " + tiling_repr_file +
196+ " --input-configs " + input_configs_file + " --topn " + std::to_string(options.topn) +
197+ " --perf-order " + options.perf_order;
198+ if (!std::string(HOST_DYNAMIC_SHAPE_ARGS).empty()) {
199+ cmd += " --dynamic-shape-args " + std::string(HOST_DYNAMIC_SHAPE_ARGS);
200+ }
201+ if (HOST_VERIFY_EMPTY_CONFIG != 0) {
202+ cmd += " --verify-empty-config";
203+ }
204+ if (options.check_z0t_positive) {
205+ cmd += " --check-z0t-positive";
206+ }
207+ const int ret = RunCommand(cmd + " 2>&1");
208+ if (ret != 0) {
209+ std::printf("host helper failed, ret=%d\n", ret);
210+ }
211+ return ret;
212+}
213+ 
214+struct KernelCompileOptions {
215+ std::string graph_name;
216+ std::string tiling_repr;
217+};
218+ 
219+inline int RunKernelCompile(const std::string &tiling_def, const std::string &device_code,
220+ const std::string &output_file, const std::string &work_dir,
221+ const KernelCompileOptions &options) {
222+ RunCommand("mkdir -p " + work_dir);
223+ WriteFile(work_dir + "/device_tiling_def.h", tiling_def);
224+ WriteFile(work_dir + "/device_impl.cpp", device_code);
225+ std::string repr_arg;
226+ if (!options.tiling_repr.empty()) {
227+ WriteFile(work_dir + "/tiling_repr.txt", options.tiling_repr);
228+ repr_arg = ", tiling_repr=open('" + work_dir + "/tiling_repr.txt').read()";
229+ }
230+ const std::string script_path = work_dir + "/run_kernel_compile.py";
231+ const std::string script =
232+ PythonPreamble() + KernelCompileScript(options.graph_name, output_file, work_dir, repr_arg);
233+ return RunPythonScript(script_path, script, ASCEND_HOME_PATH, "kernel_compile(" + work_dir + ")");
234+}
235+ 
24struct SplitCompileDlHandle {236struct SplitCompileDlHandle {
25 void *ptr = nullptr;237 void *ptr = nullptr;
26 explicit SplitCompileDlHandle(void *p) : ptr(p) {}238 explicit SplitCompileDlHandle(void *p) : ptr(p) {}
@@ -0,0 +1,51 @@
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 AUTOFUSE_TESTS_ST_BACKEND_E2E_COMMON_INDUCTOR_SPLIT_COMPILE_CONFIG_H_
12+#define AUTOFUSE_TESTS_ST_BACKEND_E2E_COMMON_INDUCTOR_SPLIT_COMPILE_CONFIG_H_
13+ 
14+#ifndef HOST_CODE_FILE
15+#define HOST_CODE_FILE ""
16+#endif
17+#ifndef DEVICE_CODE_FILE
18+#define DEVICE_CODE_FILE ""
19+#endif
20+#ifndef OUTPUT_DIR
21+#define OUTPUT_DIR ""
22+#endif
23+#ifndef HOST_HELPER_BIN
24+#define HOST_HELPER_BIN ""
25+#endif
26+#ifndef HOST_DYNAMIC_SHAPE_ARGS
27+#define HOST_DYNAMIC_SHAPE_ARGS ""
28+#endif
29+#ifndef HOST_INPUT_CONFIGS_JSON
30+#define HOST_INPUT_CONFIGS_JSON "[]"
31+#endif
32+#ifndef HOST_TOPN
33+#define HOST_TOPN 4
34+#endif
35+#ifndef HOST_PERF_ORDER
36+#define HOST_PERF_ORDER "ascending-skip-first"
37+#endif
38+#ifndef HOST_VERIFY_EMPTY_CONFIG
39+#define HOST_VERIFY_EMPTY_CONFIG 0
40+#endif
41+#ifndef PYAUTOFUSE_DIR
42+#define PYAUTOFUSE_DIR ""
43+#endif
44+#ifndef AUTOFUSE_PYTHON_DIR
45+#define AUTOFUSE_PYTHON_DIR ""
46+#endif
47+#ifndef ASCEND_HOME_PATH
48+#define ASCEND_HOME_PATH ""
49+#endif
50+ 
51+#endif // AUTOFUSE_TESTS_ST_BACKEND_E2E_COMMON_INDUCTOR_SPLIT_COMPILE_CONFIG_H_
@@ -18,212 +18,19 @@
18#include <string>18#include <string>
19#include <sys/wait.h>19#include <sys/wait.h>
20 20 
21-#ifndef HOST_CODE_FILE21+#include "../common/inductor_split_compile_common.h"
22-#define HOST_CODE_FILE ""22+#include "../common/inductor_split_compile_config.h"
23-#endif
24-#ifndef DEVICE_CODE_FILE
25-#define DEVICE_CODE_FILE ""
26-#endif
27-#ifndef OUTPUT_DIR
28-#define OUTPUT_DIR ""
29-#endif
30-#ifndef HOST_HELPER_BIN
31-#define HOST_HELPER_BIN ""
32-#endif
33-#ifndef HOST_DYNAMIC_SHAPE_ARGS
34-#define HOST_DYNAMIC_SHAPE_ARGS ""
35-#endif
36-#ifndef HOST_INPUT_CONFIGS_JSON
37-#define HOST_INPUT_CONFIGS_JSON "[]"
38-#endif
39-#ifndef HOST_TOPN
40-#define HOST_TOPN 4
41-#endif
42-#ifndef HOST_PERF_ORDER
43-#define HOST_PERF_ORDER "ascending-skip-first"
44-#endif
45-#ifndef HOST_VERIFY_EMPTY_CONFIG
46-#define HOST_VERIFY_EMPTY_CONFIG 0
47-#endif
48 23 
49namespace {24namespace {
50 25 
51-std::string ReadFile(const std::string &path) {26+using autofuse::tests::FileExists;
52- std::ifstream in(path);27+using autofuse::tests::ReadFile;
53- std::stringstream buf;
54- buf << in.rdbuf();
55- return buf.str();
56-}
57 28 
58-bool WriteFile(const std::string &path, const std::string &content) {29+constexpr const char *kGraphName = "inductor_matmul_elemwise";
59- std::ofstream out(path);
60- if (!out.is_open()) return false;
61- out << content;
62- return true;
63-}
64- 
65-int RunCommand(const std::string &cmd) {
66- int status = std::system(cmd.c_str());
67- if (WIFEXITED(status)) return WEXITSTATUS(status);
68- return -1;
69-}
70- 
71-bool FileExists(const std::string &path) {
72- std::ifstream f(path);
73- return f.good();
74-}
75- 
76-bool HasCxx11AbiSymbols(const std::string &path) {
77- return RunCommand("nm -D " + path + " 2>/dev/null | c++filt | grep -q 'std::__cxx11'") == 0;
78-}
79- 
80-#ifndef PYAUTOFUSE_DIR
81-#define PYAUTOFUSE_DIR ""
82-#endif
83-#ifndef AUTOFUSE_PYTHON_DIR
84-#define AUTOFUSE_PYTHON_DIR ""
85-#endif
86-#ifndef ASCEND_HOME_PATH
87-#define ASCEND_HOME_PATH ""
88-#endif
89- 
90-std::string PythonPreamble() {
91- return "import sys, os, traceback\n"
92- "pkg_dir = os.path.join('" +
93- std::string(OUTPUT_DIR) +
94- "', 'autofuse_pkg')\n"
95- "os.makedirs(pkg_dir, exist_ok=True)\n"
96- "autofuse_dir = os.path.join(pkg_dir, 'autofuse')\n"
97- "if os.path.islink(autofuse_dir) or os.path.isfile(autofuse_dir):\n"
98- " os.unlink(autofuse_dir)\n"
99- "os.makedirs(autofuse_dir, exist_ok=True)\n"
100- "for name in os.listdir('" +
101- std::string(AUTOFUSE_PYTHON_DIR) +
102- "'):\n"
103- " src = os.path.join('" +
104- std::string(AUTOFUSE_PYTHON_DIR) +
105- "', name)\n"
106- " dst = os.path.join(autofuse_dir, name)\n"
107- " if not os.path.lexists(dst):\n"
108- " os.symlink(src, dst)\n"
109- "pyautofuse_src = os.path.join('" +
110- std::string(PYAUTOFUSE_DIR) +
111- "', 'pyautofuse.so')\n"
112- "if not os.path.exists(pyautofuse_src):\n"
113- " raise FileNotFoundError(pyautofuse_src)\n"
114- "pyautofuse_dst = os.path.join(autofuse_dir, 'pyautofuse.so')\n"
115- "if os.path.lexists(pyautofuse_dst):\n"
116- " os.unlink(pyautofuse_dst)\n"
117- "os.symlink(pyautofuse_src, pyautofuse_dst)\n"
118- "sys.path.insert(0, pkg_dir)\n"
119- "import autofuse.ascendc_compile as _ac\n"
120- "_ac.ASCEND_PATH = '" +
121- std::string(ASCEND_HOME_PATH) + "'\n";
122-}
123- 
124-int RunHostCompile(const std::string &tiling_def, const std::string &host_code, const std::string &output_file) {
125- WriteFile(OUTPUT_DIR "/host_tiling_def.h", tiling_def);
126- WriteFile(OUTPUT_DIR "/host_impl.cpp", host_code);
127- 
128- std::string script_path = std::string(OUTPUT_DIR) + "/run_host_compile.py";
129- WriteFile(script_path, PythonPreamble() +
130- "try:\n"
131- " from autofuse.compile_adapter import host_compile\n"
132- " import os\n"
133- " os.makedirs('" +
134- std::string(OUTPUT_DIR) +
135- "/host_out', exist_ok=True)\n"
136- " td = open('" +
137- std::string(OUTPUT_DIR) +
138- "/host_tiling_def.h').read()\n"
139- " hc = open('" +
140- std::string(OUTPUT_DIR) +
141- "/host_impl.cpp').read()\n"
142- " host_compile(td, hc, [\n"
143- " '--graph_name=inductor_matmul_elemwise',\n"
144- " '--output_file=" +
145- output_file +
146- "',\n"
147- " '--output_path=" +
148- std::string(OUTPUT_DIR) +
149- "/host_out',\n"
150- " '--soc_version=Ascend910B',\n"
151- " '--compile_options=-Werror'])\n"
152- "except Exception:\n"
153- " traceback.print_exc()\n"
154- " sys.exit(1)\n");
155- 
156- std::string cmd = "ASCEND_HOME_PATH=" + std::string(ASCEND_HOME_PATH) + " python3 " + script_path + " 2>&1";
157- int ret = RunCommand(cmd);
158- if (ret != 0) printf("host_compile failed, ret=%d\n", ret);
159- return ret;
160-}
161- 
162-int RunHostHelper(const std::string &host_bin, const std::string &tiling_repr_file) {
163- const std::string input_configs_file = OUTPUT_DIR "/host_input_configs.json";
164- WriteFile(input_configs_file, HOST_INPUT_CONFIGS_JSON);
165- std::string cmd = std::string(HOST_HELPER_BIN) + " --host-so " + host_bin + " --tiling-repr-out " + tiling_repr_file +
166- " --input-configs " + input_configs_file + " --topn " + std::to_string(HOST_TOPN) +
167- " --perf-order " + std::string(HOST_PERF_ORDER);
168- if (!std::string(HOST_DYNAMIC_SHAPE_ARGS).empty()) {
169- cmd += " --dynamic-shape-args " + std::string(HOST_DYNAMIC_SHAPE_ARGS);
170- }
171- if (HOST_VERIFY_EMPTY_CONFIG != 0) {
172- cmd += " --verify-empty-config";
173- }
174- cmd += " 2>&1";
175- int ret = RunCommand(cmd);
176- if (ret != 0) printf("host helper failed, ret=%d\n", ret);
177- return ret;
178-}
179 30 
180int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file,31int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file,
181 const std::string &work_dir, const std::string &tiling_repr) {32 const std::string &work_dir, const std::string &tiling_repr) {
182- std::string mkdir_cmd = "mkdir -p " + work_dir;33+ return autofuse::tests::RunKernelCompile(tiling_def, device_code, output_file, work_dir, {kGraphName, tiling_repr});
183- RunCommand(mkdir_cmd);
184- WriteFile(work_dir + "/device_tiling_def.h", tiling_def);
185- WriteFile(work_dir + "/device_impl.cpp", device_code);
186- 
187- std::string repr_arg;
188- if (!tiling_repr.empty()) {
189- WriteFile(work_dir + "/tiling_repr.txt", tiling_repr);
190- repr_arg = ", tiling_repr=open('" + work_dir + "/tiling_repr.txt').read()";
191- }
192- 
193- std::string script_path = work_dir + "/run_kernel_compile.py";
194- WriteFile(script_path, PythonPreamble() +
195- "try:\n"
196- " from autofuse.compile_adapter import kernel_compile\n"
197- " import os\n"
198- " os.makedirs('" +
199- work_dir +
200- "', exist_ok=True)\n"
201- " td = open('" +
202- work_dir +
203- "/device_tiling_def.h').read()\n"
204- " dc = open('" +
205- work_dir +
206- "/device_impl.cpp').read()\n"
207- " argv = ['--graph_name=inductor_matmul_elemwise',\n"
208- " '--output_file=" +
209- output_file +
210- "',\n"
211- " '--output_path=" +
212- work_dir +
213- "',\n"
214- " '--soc_version=Ascend910B',\n"
215- " '--compile_options=-D_GLIBCXX_USE_CXX11_ABI=0']\n"
216- " kernel_compile(td, dc, argv" +
217- repr_arg +
218- ")\n"
219- "except Exception:\n"
220- " traceback.print_exc()\n"
221- " sys.exit(1)\n");
222- 
223- std::string cmd = "ASCEND_HOME_PATH=" + std::string(ASCEND_HOME_PATH) + " python3 " + script_path + " 2>&1";
224- int ret = RunCommand(cmd);
225- if (ret != 0) printf("kernel_compile failed, ret=%d, work_dir=%s\n", ret, work_dir.c_str());
226- return ret;
227}34}
228 35 
229struct DlHandle {36struct DlHandle {
@@ -296,11 +103,11 @@ TEST_F(TestBackendInductorMatmulElemwiseSplitCompile, SplitCompileChainWorks) {
296 EXPECT_EQ(host_code.find("AscirCompileAndLaunch"), std::string::npos);103 EXPECT_EQ(host_code.find("AscirCompileAndLaunch"), std::string::npos);
297 104 
298 const std::string host_bin = OUTPUT_DIR "/inductor_matmul_elemwise_host.so";105 const std::string host_bin = OUTPUT_DIR "/inductor_matmul_elemwise_host.so";
299- ASSERT_EQ(RunHostCompile(tiling_def, host_code, host_bin), 0);106+ ASSERT_EQ(autofuse::tests::RunHostCompile(tiling_def, host_code, host_bin, "inductor_matmul_elemwise", "-Werror"), 0);
300 ASSERT_TRUE(FileExists(host_bin)) << "host so not found: " << host_bin;107 ASSERT_TRUE(FileExists(host_bin)) << "host so not found: " << host_bin;
301- ASSERT_TRUE(HasCxx11AbiSymbols(host_bin)) << "host so should use ABI=1: " << host_bin;108+ ASSERT_TRUE(autofuse::tests::HasCxx11AbiSymbols(host_bin)) << "host so should use ABI=1: " << host_bin;
302 const std::string tiling_repr_file = OUTPUT_DIR "/tiling_repr.txt";109 const std::string tiling_repr_file = OUTPUT_DIR "/tiling_repr.txt";
303- ASSERT_EQ(RunHostHelper(host_bin, tiling_repr_file), 0);110+ ASSERT_EQ(autofuse::tests::RunHostHelper(host_bin, tiling_repr_file), 0);
304 std::string tiling_repr = ReadFile(tiling_repr_file);111 std::string tiling_repr = ReadFile(tiling_repr_file);
305 ASSERT_FALSE(tiling_repr.empty());112 ASSERT_FALSE(tiling_repr.empty());
306 113 
@@ -21,210 +21,18 @@
21#include <string>21#include <string>
22#include <sys/wait.h>22#include <sys/wait.h>
23 23 
24-#ifndef HOST_CODE_FILE24+#include "../common/inductor_split_compile_config.h"
25-#define HOST_CODE_FILE ""
26-#endif
27-#ifndef DEVICE_CODE_FILE
28-#define DEVICE_CODE_FILE ""
29-#endif
30-#ifndef OUTPUT_DIR
31-#define OUTPUT_DIR ""
32-#endif
33-#ifndef HOST_HELPER_BIN
34-#define HOST_HELPER_BIN ""
35-#endif
36-#ifndef HOST_DYNAMIC_SHAPE_ARGS
37-#define HOST_DYNAMIC_SHAPE_ARGS ""
38-#endif
39-#ifndef HOST_INPUT_CONFIGS_JSON
40-#define HOST_INPUT_CONFIGS_JSON "[]"
41-#endif
42-#ifndef HOST_TOPN
43-#define HOST_TOPN 4
44-#endif
45-#ifndef HOST_PERF_ORDER
46-#define HOST_PERF_ORDER "ascending-skip-first"
47-#endif
48-#ifndef HOST_VERIFY_EMPTY_CONFIG
49-#define HOST_VERIFY_EMPTY_CONFIG 0
50-#endif
51 25 
52namespace {26namespace {
53 27 
54-std::string ReadFile(const std::string &path) {28+using autofuse::tests::FileExists;
55- std::ifstream in(path);29+using autofuse::tests::ReadFile;
56- std::stringstream buf;
57- buf << in.rdbuf();
58- return buf.str();
59-}
60 30 
61-bool WriteFile(const std::string &path, const std::string &content) {31+constexpr const char *kGraphName = "inductor_tail_brc_tail_reduce";
62- std::ofstream out(path);
63- if (!out.is_open()) return false;
64- out << content;
65- return true;
66-}
67- 
68-int RunCommand(const std::string &cmd) {
69- int status = std::system(cmd.c_str());
70- if (WIFEXITED(status)) return WEXITSTATUS(status);
71- return -1;
72-}
73- 
74-bool FileExists(const std::string &path) {
75- std::ifstream f(path);
76- return f.good();
77-}
78- 
79-bool HasCxx11AbiSymbols(const std::string &path) {
80- return RunCommand("nm -D " + path + " 2>/dev/null | c++filt | grep -q 'std::__cxx11'") == 0;
81-}
82- 
83-#ifndef PYAUTOFUSE_DIR
84-#define PYAUTOFUSE_DIR ""
85-#endif
86-#ifndef AUTOFUSE_PYTHON_DIR
87-#define AUTOFUSE_PYTHON_DIR ""
88-#endif
89-#ifndef ASCEND_HOME_PATH
90-#define ASCEND_HOME_PATH ""
91-#endif
92- 
93-std::string PythonPreamble() {
94- return "import sys, os, traceback\n"
95- "pkg_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'autofuse_pkg')\n"
96- "os.makedirs(pkg_dir, exist_ok=True)\n"
97- "autofuse_dir = os.path.join(pkg_dir, 'autofuse')\n"
98- "if os.path.islink(autofuse_dir) or os.path.isfile(autofuse_dir):\n"
99- " os.unlink(autofuse_dir)\n"
100- "os.makedirs(autofuse_dir, exist_ok=True)\n"
101- "for name in os.listdir('" +
102- std::string(AUTOFUSE_PYTHON_DIR) +
103- "'):\n"
104- " src = os.path.join('" +
105- std::string(AUTOFUSE_PYTHON_DIR) +
106- "', name)\n"
107- " dst = os.path.join(autofuse_dir, name)\n"
108- " if not os.path.lexists(dst):\n"
109- " os.symlink(src, dst)\n"
110- "pyautofuse_src = os.path.join('" +
111- std::string(PYAUTOFUSE_DIR) +
112- "', 'pyautofuse.so')\n"
113- "if not os.path.exists(pyautofuse_src):\n"
114- " raise FileNotFoundError(pyautofuse_src)\n"
115- "pyautofuse_dst = os.path.join(autofuse_dir, 'pyautofuse.so')\n"
116- "if os.path.lexists(pyautofuse_dst):\n"
117- " os.unlink(pyautofuse_dst)\n"
118- "os.symlink(pyautofuse_src, pyautofuse_dst)\n"
119- "sys.path.insert(0, pkg_dir)\n"
120- "import autofuse.ascendc_compile as _ac\n"
121- "_ac.ASCEND_PATH = '" +
122- std::string(ASCEND_HOME_PATH) + "'\n";
123-}
124- 
125-int RunHostCompile(const std::string &tiling_def, const std::string &host_code, const std::string &output_file) {
126- WriteFile(OUTPUT_DIR "/host_tiling_def.h", tiling_def);
127- WriteFile(OUTPUT_DIR "/host_impl.cpp", host_code);
128- 
129- std::string script_path = std::string(OUTPUT_DIR) + "/run_host_compile.py";
130- WriteFile(script_path, PythonPreamble() +
131- "try:\n"
132- " from autofuse.compile_adapter import host_compile\n"
133- " import os\n"
134- " os.makedirs('" +
135- std::string(OUTPUT_DIR) +
136- "/host_out', exist_ok=True)\n"
137- " td = open('" +
138- std::string(OUTPUT_DIR) +
139- "/host_tiling_def.h').read()\n"
140- " hc = open('" +
141- std::string(OUTPUT_DIR) +
142- "/host_impl.cpp').read()\n"
143- " host_compile(td, hc, [\n"
144- " '--graph_name=inductor_tail_brc_tail_reduce',\n"
145- " '--output_file=" +
146- output_file +
147- "',\n"
148- " '--output_path=" +
149- std::string(OUTPUT_DIR) +
150- "/host_out',\n"
151- " '--soc_version=Ascend910B',\n"
152- " '--compile_options=-Werror'])\n"
153- "except Exception:\n"
154- " traceback.print_exc()\n"
155- " sys.exit(1)\n");
156- 
157- std::string cmd = "ASCEND_HOME_PATH=" + std::string(ASCEND_HOME_PATH) + " python3 " + script_path + " 2>&1";
158- int ret = RunCommand(cmd);
159- if (ret != 0) printf("host_compile failed, ret=%d\n", ret);
160- return ret;
161-}
162- 
163-int RunHostHelper(const std::string &host_bin, const std::string &tiling_repr_file) {
164- const std::string input_configs_file = OUTPUT_DIR "/host_input_configs.json";
165- WriteFile(input_configs_file, HOST_INPUT_CONFIGS_JSON);
166- std::string cmd = std::string(HOST_HELPER_BIN) + " --host-so " + host_bin + " --tiling-repr-out " + tiling_repr_file +
167- " --input-configs " + input_configs_file + " --topn " + std::to_string(HOST_TOPN) +
168- " --perf-order " + std::string(HOST_PERF_ORDER);
169- if (!std::string(HOST_DYNAMIC_SHAPE_ARGS).empty()) {
170- cmd += " --dynamic-shape-args " + std::string(HOST_DYNAMIC_SHAPE_ARGS);
171- }
172- if (HOST_VERIFY_EMPTY_CONFIG != 0) {
173- cmd += " --verify-empty-config";
174- }
175- cmd += " 2>&1";
176- int ret = RunCommand(cmd);
177- if (ret != 0) printf("host helper failed, ret=%d\n", ret);
178- return ret;
179-}
180 32 
181int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file,33int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file,
182 const std::string &work_dir, const std::string &tiling_repr) {34 const std::string &work_dir, const std::string &tiling_repr) {
183- std::string mkdir_cmd = "mkdir -p " + work_dir;35+ return autofuse::tests::RunKernelCompile(tiling_def, device_code, output_file, work_dir, {kGraphName, tiling_repr});
184- RunCommand(mkdir_cmd);
185- WriteFile(work_dir + "/device_tiling_def.h", tiling_def);
186- WriteFile(work_dir + "/device_impl.cpp", device_code);
187- 
188- std::string repr_arg;
189- if (!tiling_repr.empty()) {
190- WriteFile(work_dir + "/tiling_repr.txt", tiling_repr);
191- repr_arg = ", tiling_repr=open('" + work_dir + "/tiling_repr.txt').read()";
192- }
193- 
194- std::string script_path = work_dir + "/run_kernel_compile.py";
195- WriteFile(script_path, PythonPreamble() +
196- "try:\n"
197- " from autofuse.compile_adapter import kernel_compile\n"
198- " import os\n"
199- " os.makedirs('" +
200- work_dir +
201- "', exist_ok=True)\n"
202- " td = open('" +
203- work_dir +
204- "/device_tiling_def.h').read()\n"
205- " dc = open('" +
206- work_dir +
207- "/device_impl.cpp').read()\n"
208- " argv = ['--graph_name=inductor_tail_brc_tail_reduce',\n"
209- " '--output_file=" +
210- output_file +
211- "',\n"
212- " '--output_path=" +
213- work_dir +
214- "',\n"
215- " '--soc_version=Ascend910B',\n"
216- " '--compile_options=-D_GLIBCXX_USE_CXX11_ABI=0']\n"
217- " kernel_compile(td, dc, argv" +
218- repr_arg +
219- ")\n"
220- "except Exception:\n"
221- " traceback.print_exc()\n"
222- " sys.exit(1)\n");
223- 
224- std::string cmd = "ASCEND_HOME_PATH=" + std::string(ASCEND_HOME_PATH) + " python3 " + script_path + " 2>&1";
225- int ret = RunCommand(cmd);
226- if (ret != 0) printf("kernel_compile failed, ret=%d, work_dir=%s\n", ret, work_dir.c_str());
227- return ret;
228}36}
229 37 
230} // namespace38} // namespace
@@ -266,11 +74,12 @@ TEST_F(TestBackendInductorTailBrcTailReduceSplitCompile, SplitCompileChainWorks)
266 PrepareInputs(tiling_def, host_code, device_code);74 PrepareInputs(tiling_def, host_code, device_code);
267 75 
268 const std::string host_bin = OUTPUT_DIR "/inductor_tail_brc_tail_reduce_host.so";76 const std::string host_bin = OUTPUT_DIR "/inductor_tail_brc_tail_reduce_host.so";
269- ASSERT_EQ(RunHostCompile(tiling_def, host_code, host_bin), 0);77+ ASSERT_EQ(
78+ autofuse::tests::RunHostCompile(tiling_def, host_code, host_bin, "inductor_tail_brc_tail_reduce", "-Werror"), 0);
270 ASSERT_TRUE(FileExists(host_bin)) << "host so not found: " << host_bin;79 ASSERT_TRUE(FileExists(host_bin)) << "host so not found: " << host_bin;
271- ASSERT_TRUE(HasCxx11AbiSymbols(host_bin)) << "host so should use ABI=1: " << host_bin;80+ ASSERT_TRUE(autofuse::tests::HasCxx11AbiSymbols(host_bin)) << "host so should use ABI=1: " << host_bin;
272 const std::string tiling_repr_file = OUTPUT_DIR "/tiling_repr.txt";81 const std::string tiling_repr_file = OUTPUT_DIR "/tiling_repr.txt";
273- ASSERT_EQ(RunHostHelper(host_bin, tiling_repr_file), 0);82+ ASSERT_EQ(autofuse::tests::RunHostHelper(host_bin, tiling_repr_file), 0);
274 std::string tiling_repr = ReadFile(tiling_repr_file);83 std::string tiling_repr = ReadFile(tiling_repr_file);
275 ASSERT_FALSE(tiling_repr.empty());84 ASSERT_FALSE(tiling_repr.empty());
276 85