已合并
feat: 【编译性能优化】TilingFunc支持按需引用头文件 #1530
zhang_shengjie创建于 7月28日
feat: 【编译性能优化】TilingFunc支持按需引用头文件 #1530
已合并
共 47 个文件变更+3217-2224
| @@ -110,10 +110,20 @@ const std::string kIsTrue = "1"; | |||
| 110 | const std::string kIsFalse = "0"; | 110 | const std::string kIsFalse = "0"; |
| 111 | const std::string kTilingFuncIdentify = "TilingFunc"; | 111 | const std::string kTilingFuncIdentify = "TilingFunc"; |
| 112 | const std::string kTilingHeadIdentify = "TilingHead"; | 112 | const 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"; | ||
| 113 | const std::string kTilingSolverIdentify = "solver_func"; | 118 | const std::string kTilingSolverIdentify = "solver_func"; |
| 114 | const std::string kTilingScheduleGroupTailIdentify = "schedule_group_tail"; | 119 | const std::string kTilingScheduleGroupTailIdentify = "schedule_group_tail"; |
| 115 | const std::string kDefaultTilingDataFileName = "tiling_data.h"; | 120 | const std::string kDefaultTilingDataFileName = "tiling_data.h"; |
| 116 | const std::string kDefaultTilingHeadFileName = "autofuse_tiling_func_common.h"; | 121 | const 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"; | ||
| 117 | const std::string kDefaultTilingFuncFileName = "tiling_func.cpp"; | 127 | const std::string kDefaultTilingFuncFileName = "tiling_func.cpp"; |
| 118 | const std::string kHighPrecision = "high_precision"; | 128 | const std::string kHighPrecision = "high_precision"; |
| 119 | const std::string kDurationLevelName = "duration_level"; | 129 | const std::string kDurationLevelName = "duration_level"; |
| @@ -463,6 +463,8 @@ af::Status GetConfusionTransposeTilingHeadFiles([[maybe_unused]] const std::stri | |||
| 463 | 463 | ||
| 464 | 464 | ||
| 465 | 465 | ||
| 466 | + | ||
| 467 | + | ||
| 466 | using graphStatus = uint32_t; | 468 | using graphStatus = uint32_t; |
| 467 | const graphStatus GRAPH_FAILED = 0xFFFFFFFF; | 469 | const graphStatus GRAPH_FAILED = 0xFFFFFFFF; |
| 468 | const graphStatus GRAPH_SUCCESS = 0; | 470 | const 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 = 7 | 482 | TRANSPOSE_INVALID = 7 |
| 481 | }; | 483 | }; |
| 484 | + | ||
| 482 | )"; | 485 | )"; |
| 483 | 486 | ||
| 484 | code_string = kHeaderContent; | 487 | code_string = kHeaderContent; |
| @@ -80,14 +80,22 @@ void AxesReorderTilingCodeGenImpl::ConfigureSolverPassManagerCommon(SolverPassMa | |||
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | af::Status AxesReorderTilingCodeGenImpl::GenSolverBaseClass() { | 82 | af::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 | } // namespace | 104 | } // namespace |
| 63 | 105 | ||
| 64 | af::Status OperatorLevelCacheGen::GenFixedSizeHashMapDef(ge::CodePrinter &code_printer) { | 106 | af::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"( |
| 106 | bool FindOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, )" + | 135 | bool 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"( |
| 119 | bool SaveOperatorCache(std::array<uint32_t, kInputShapeSize>& input_shapes, const )" + | 148 | bool 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存储,无需线程ID | 227 | * 线程级别的缓存上下文,使用thread_local存储,无需线程ID |
| 207 | */ | 228 | */ |
| 229 | +template <typename TilingData> | ||
| 208 | class TilingCacheContext { | 230 | class 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() { | |||
| 222 | private: | 243 | private: |
| 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() { | |||
| 238 | public: | 260 | public: |
| 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_name | 297 | + << "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_name | 317 | + << "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::Status | 54 | * @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::Status | 61 | * @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::Status | 86 | * @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::Status | 104 | * @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 cache | 120 | } // 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 | ||
| 417 | std::string SolverPassManager::GenCommonBaseClassesHead(std::vector<ArgsManager> args_managers) { | 417 | std::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 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 18 | ||
| @@ -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 | } // namespace | 408 | } // 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 | + | ||
| 397 | inline void SetTilingDefinition(const std::set<std::string> &var_names, const std::string ¶m_name, | 578 | inline void SetTilingDefinition(const std::set<std::string> &var_names, const std::string ¶m_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 | |||
| 535 | af::Status TilingCodeGenImpl::GenDurationCommonCode() { | 716 | af::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 | + | ||
| 796 | void TilingCodeGenImpl::GenPgoHeaderCodesTail() { | 1054 | void 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 | ||
| 841 | af::Status TilingCodeGenImpl::GenHeaderInclude() { | 1078 | af::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 | ||
| 1432 | af::Status TilingCodeGenImpl::GenExpressionMacro() { | 1669 | af::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 ¯o : 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 | ||
| 1491 | af::Status TilingCodeGenImpl::GenToolFuncs() { | 1734 | af::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 | ||
| 2057 | af::Status TilingCodeGenImpl::GenFindCacheAndSaveCache() { | 2307 | af::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() { | |||
| 2616 | af::Status TilingCodeGenImpl::GenPGOSearchTilingKey() { | 2873 | af::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() { | |||
| 2784 | void TilingCodeGenImpl::GenTilingHeadMultiGroup() { | 3044 | void 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 | + | ||
| 2794 | af::Status TilingCodeGenImpl::GenTilingHead(std::map<std::string, std::string> &tiling_res, | 3104 | af::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、生成总TilingData | 3110 | // 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, | |||
| 3898 | af::Status TilingCodeGenImpl::GenFusedScheduleResultsGetTilingDefine(const FusedGraphNamespaceMap &namespace_map) { | 4209 | af::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 | ||
| 4226 | af::Status TilingCodeGenImpl::GenGetTilingFunctionBody(bool use_cache, bool is_tail, const std::string &cache_used) { | 4542 | af::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 | ||
| 4466 | af::Status TilingCodeGenImpl::GenGetPerf() { | 4790 | af::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 | ||
| 4477 | af::Status TilingCodeGenImpl::GenGetSummary() { | 4802 | af::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 | + | ||
| 4514 | af::Status TilingCodeGenImpl::GenTiling(std::map<std::string, std::string> &tiling_res, | 4927 | af::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 | ||
| 4567 | af::Status TilingCodeGenImpl::GenReuseGroupTilingWrapperGetTiling( | 4962 | af::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 GetSummary | 5048 | // 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 group | 5074 | // 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 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -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 | } // namespace | 53 | } // namespace |
| 35 | 54 | ||
| 36 | af::Status TilingCodeGenerator::GenTilingCode(const std::string &op_type, const TilingModelInfo &model_infos, | 55 | af::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 ¶ms, | |||
| 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 ¶ms, | |||
| 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 | + | ||
| 238 | af::Status TilingCodeGenerator::CollectModelInfosAndMetadata( | 274 | af::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 att | 77 | } // namespace att |
| 75 | 78 | ||
| @@ -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 | + | ||
| 109 | Status CombineTilings(const std::map<std::string, std::string> &tiling_file_name_to_content, std::string &result) { | 117 | Status 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 | - | ||
| 174 | std::string RemoveSplitCppIncludes(const std::string &content) { | 155 | std::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 | ||
| 178 | void AppendSplitSource(const std::string &key, const std::string &content, std::string &result) { | 175 | void 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 | - | ||
| 190 | std::string BuildSplitHeaderContent(const std::map<std::string, std::string> &tiling_file_name_to_content) { | 181 | std::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 | ||
| 201 | bool ShouldSkipSplitCppSource(const std::string &key) { | 185 | bool 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 | + | ||
| 206 | Status CombineTilingsWithSplitMarkers(const std::map<std::string, std::string> &tiling_file_name_to_content, | 217 | Status 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 | 12 | ||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | + | ||
| 15 | 16 | ||
| 16 | 17 | ||
| 17 | 18 | ||
| @@ -36,6 +37,7 @@ | |||
| 36 | 37 | ||
| 37 | 38 | ||
| 38 | 39 | ||
| 40 | + | ||
| 39 | 41 | ||
| 40 | namespace codegen { | 42 | namespace codegen { |
| 41 | using optimize::AscGraphInfoComplete; | 43 | using 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 | ||
| 81 | void AppendCvSafetyAivOnlyModeDef(std::stringstream &ss, bool is_batch) { | 297 | void 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 | - | ||
| 1912 | std::map<std::string, std::string> TilingLib::GenerateCVFusion(const ascir::FusedScheduledResult &fused_schedule_result, | 2113 | std::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 | + | ||
| 2038 | std::string TilingLib::GetTilingIncludeHead(bool is_cv) const { | 2284 | std::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 | + | ||
| 2062 | std::map<std::string, std::string> TilingLib::GetTilingHeaders(const ascir::FusedScheduledResult &fused_schedule_result, | 2327 | std::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 | ||
| 18 | namespace codegen { | 18 | namespace codegen { |
| 19 | const std::string kTilingHeadIdentify = "TilingHead"; | 19 | const 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"; | ||
| 20 | const std::string kTilingDataIdentify = "TilingData"; | 28 | const std::string kTilingDataIdentify = "TilingData"; |
| 21 | const std::string kTilingHeadGuard = "__AUTOFUSE_TILING_FUNC_COMMON_H__"; | 29 | const std::string kTilingHeadGuard = "__AUTOFUSE_TILING_FUNC_COMMON_H__"; |
| 22 | const std::string kTilingHeadInclude = "#include \"autofuse_tiling_func_common.h\""; | 30 | const 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\""; | ||
| 23 | const std::string kTilingHeadCceKtTestGuard = "#ifndef __CCE_KT_TEST__"; | 39 | const 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\""; | ||
| 26 | const std::string kTilingDefAndConstIdentify = "tiling_def_and_tiling_const"; | 40 | const std::string kTilingDefAndConstIdentify = "tiling_def_and_tiling_const"; |
| 27 | const std::string kCubeTilingHeadInclude = "#include \"autofuse_cube_tiling_data.h\""; | 41 | const std::string kCubeTilingHeadInclude = "#include \"autofuse_cube_tiling_data.h\""; |
| 28 | const std::string kCubeKernelTilingWrapperHpp = "ACubeKernelTilingWrapperHpp"; | 42 | const 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 | 24 | ||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | + | ||
| 27 | 28 | ||
| 28 | 29 | ||
| 30 | + | ||
| 29 | 31 | ||
| 30 | 32 | ||
| 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 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 | + | ||
| @@ -28,7 +28,7 @@ import tbe.common.utils.log as logger | |||
| 28 | # Python3 lib pyautofuse.so | 28 | # Python3 lib pyautofuse.so |
| 29 | from .pyautofuse import Schedule, CodeGen, ascir | 29 | from .pyautofuse import Schedule, CodeGen, ascir |
| 30 | from .ascbc_kernel_compile import ascbc_kernel_compile, camel_to_snake | 30 | from .ascbc_kernel_compile import ascbc_kernel_compile, camel_to_snake |
| 31 | -from .compile_adapter import get_pgo_env_flag, get_pgo_topn | 31 | +from .compile_adapter import TILING_HEADER_FILES, get_pgo_env_flag, get_pgo_topn |
| 32 | from tbe.tikcpp.get_op_tiling import ( | 32 | from 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, "..", "..", "..") | |||
| 42 | timestamp_list = [] | 42 | timestamp_list = [] |
| 43 | HOST_TILING_COMPILE_JOBS = 32 | 43 | HOST_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_dir | 910 | template_dir = host_build_dir |
| 907 | ret_tiling_func_srcs = template_dict | 911 | 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", value | 923 | 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_name | 1181 | 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" | |||
| 23 | SPLIT_BEGIN_PREFIX = "// AUTOFUSE_SPLIT_FILE_BEGIN:" | 23 | SPLIT_BEGIN_PREFIX = "// AUTOFUSE_SPLIT_FILE_BEGIN:" |
| 24 | SPLIT_END_PREFIX = "// AUTOFUSE_SPLIT_FILE_END:" | 24 | SPLIT_END_PREFIX = "// AUTOFUSE_SPLIT_FILE_END:" |
| 25 | SPLIT_HEADER_KEY = "TilingHead" | 25 | SPLIT_HEADER_KEY = "TilingHead" |
| 26 | -SPLIT_HEADER_FILE = "autofuse_tiling_func_common.h" | ||
| 27 | SPLIT_HEADER_INCLUDE = '#include "autofuse_tiling_func_common.h"' | 26 | SPLIT_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 | ||
| 30 | def str2bool(v): | 49 | def str2bool(v): |
| @@ -129,25 +148,37 @@ def parse_split_marker(line, prefix): | |||
| 129 | return key | 148 | 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_sources | 161 | + 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_sources | 164 | + 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 | ||
| 147 | def parse_split_host_sources(host_impl_code): | 178 | def parse_split_host_sources(host_impl_code): |
| 148 | current_key = None | 179 | current_key = None |
| 149 | current_lines = [] | 180 | current_lines = [] |
| 150 | - header = None | 181 | + 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_keys | 207 | + current_key, current_lines, headers, cpp_sources, seen_keys |
| 177 | ) | 208 | ) |
| 178 | current_key = None | 209 | 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 | ||
| 199 | def add_split_header_include(cpp_content): | 227 | def add_split_header_include(cpp_content): |
| @@ -203,12 +231,20 @@ def add_split_header_include(cpp_content): | |||
| 203 | 231 | ||
| 204 | 232 | ||
| 205 | def write_split_host_sources(host_file_path, graph_name, host_impl_code): | 233 | def 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_files | 249 | 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 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 ¯o_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 | + | ||
| @@ -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 | 10 | ||
| 11 | + | ||
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | 14 | ||
| @@ -19,6 +20,7 @@ | |||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 24 | using namespace ge::ascir_op; | 26 | using namespace ge::ascir_op; |
| @@ -39,9 +41,9 @@ void Add_Layer_Norm_Slice_AfterQueBufAlloc(ascir::HintGraph &graph); | |||
| 39 | void Add_Layer_Norm_Welford_BeforeAutofuse(ascir::HintGraph &graph); | 41 | void Add_Layer_Norm_Welford_BeforeAutofuse(ascir::HintGraph &graph); |
| 40 | void Add_Layer_Norm_Welford_AfterScheduler(ascir::HintGraph &graph); | 42 | void Add_Layer_Norm_Welford_AfterScheduler(ascir::HintGraph &graph); |
| 41 | void Add_Layer_Norm_Welford_AfterQueBufAlloc(ascir::HintGraph &graph); | 43 | void Add_Layer_Norm_Welford_AfterQueBufAlloc(ascir::HintGraph &graph); |
| 42 | -void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result); | ||
| 43 | 44 | ||
| 44 | using namespace att; | 45 | using namespace att; |
| 46 | +using att::test::CombineTilings; | ||
| 45 | 47 | ||
| 46 | namespace { | 48 | namespace { |
| 47 | void SetStatsEnv() { | 49 | void 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 | - | ||
| 268 | const std::string kGroupParallelTilingMain = R"( | 242 | const std::string kGroupParallelTilingMain = R"( |
| 269 | 243 | ||
| 270 | 244 | ||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | + | ||
| 14 | 15 | ||
| 15 | 16 | ||
| 16 | 17 | ||
| @@ -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 | - | ||
| 465 | void CombineTilings(const std::map<std::string, std::string> &tilings, std::string &result) { | 451 | void 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 cg | 454 | } // namespace cg |
| 497 | } // namespace ascir | 455 | } // 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 | 11 | ||
| 12 | - | ||
| 13 | - | ||
| 14 | - | ||
| 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 ¯o_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 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | -#include <string> | 14 | +#include "../../../common/att/common_gen_utils.h" |
| 15 | - | ||
| 16 | - | ||
| 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 ¯o_name); | ||
| 29 | - | ||
| 30 | -} // namespace test | ||
| 31 | -} // namespace att | ||
| 32 | 15 | ||
| 33 | 16 | ||
| @@ -14,13 +14,225 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 18 | + | ||
| 17 | 19 | ||
| 18 | 20 | ||
| 19 | 21 | ||
| 22 | + | ||
| 23 | + | ||
| 20 | 24 | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 21 | 28 | ||
| 22 | namespace autofuse::tests { | 29 | namespace 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 | + | ||
| 24 | struct SplitCompileDlHandle { | 236 | struct 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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + | ||
| 48 | + | ||
| 49 | + | ||
| 50 | + | ||
| 51 | + | ||
| @@ -18,212 +18,19 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | -#ifndef HOST_CODE_FILE | 21 | +#include "../common/inductor_split_compile_common.h" |
| 22 | -#define HOST_CODE_FILE "" | 22 | +#include "../common/inductor_split_compile_config.h" |
| 23 | - | ||
| 24 | - | ||
| 25 | - | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - | ||
| 37 | - | ||
| 38 | - | ||
| 39 | - | ||
| 40 | - | ||
| 41 | - | ||
| 42 | - | ||
| 43 | - | ||
| 44 | - | ||
| 45 | - | ||
| 46 | - | ||
| 47 | - | ||
| 48 | 23 | ||
| 49 | namespace { | 24 | namespace { |
| 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 | - | ||
| 81 | - | ||
| 82 | - | ||
| 83 | - | ||
| 84 | - | ||
| 85 | - | ||
| 86 | - | ||
| 87 | - | ||
| 88 | - | ||
| 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 | ||
| 180 | int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file, | 31 | int 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 | ||
| 229 | struct DlHandle { | 36 | struct 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 | 21 | ||
| 22 | 22 | ||
| 23 | 23 | ||
| 24 | -#ifndef HOST_CODE_FILE | 24 | +#include "../common/inductor_split_compile_config.h" |
| 25 | - | ||
| 26 | - | ||
| 27 | - | ||
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - | ||
| 35 | - | ||
| 36 | - | ||
| 37 | - | ||
| 38 | - | ||
| 39 | - | ||
| 40 | - | ||
| 41 | - | ||
| 42 | - | ||
| 43 | - | ||
| 44 | - | ||
| 45 | - | ||
| 46 | - | ||
| 47 | - | ||
| 48 | - | ||
| 49 | - | ||
| 50 | - | ||
| 51 | 25 | ||
| 52 | namespace { | 26 | namespace { |
| 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 | - | ||
| 84 | - | ||
| 85 | - | ||
| 86 | - | ||
| 87 | - | ||
| 88 | - | ||
| 89 | - | ||
| 90 | - | ||
| 91 | - | ||
| 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 | ||
| 181 | int RunKernelCompile(const std::string &tiling_def, const std::string &device_code, const std::string &output_file, | 33 | int 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 | } // namespace | 38 | } // 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 | ||