* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include "codegen_tiling.h"
#include "autofuse_config/auto_fuse_config.h"
#include "common_utils.h"
#include "common/ge_common/debug/log.h"
#include "common/platform_context.h"
namespace codegen {
using namespace ascgen_utils;
using namespace ascir;
namespace {
std::string GenPgoMeasuredSearchModel() {
return R"(
inline std::string PgoMeasuredCandidateKey(const AutofuseTilingDataPerf &candidate) {
const char *ptr = reinterpret_cast<const char *>(&candidate.tiling_data);
return std::string(ptr, ptr + sizeof(AutofuseTilingData));
}
inline std::vector<AutofuseTilingDataPerf> NormalizePgoMeasuredCandidates(
std::vector<AutofuseTilingDataPerf> raw_candidates) {
std::vector<AutofuseTilingDataPerf> candidates;
candidates.reserve(raw_candidates.size());
std::unordered_set<std::string> seen;
for (auto &candidate : raw_candidates) {
const std::string key = PgoMeasuredCandidateKey(candidate);
if (!seen.insert(key).second) {
continue;
}
candidates.push_back(std::move(candidate));
}
return candidates;
}
)";
}
}
std::string TilingLib::GenPgoTilingFunc(const ascir::FusedScheduledResult &fused_schedule_result,
const std::string &tiling, codegen::PgoShapeStringStream &pgo_shape_dim,
bool is_inductor_scene, const std::string &core_num) const {
std::stringstream ss;
ss << GenPgoMeasuredSearchModel();
ss << GenPgoAutofuseTiling(fused_schedule_result, pgo_shape_dim, tiling, is_inductor_scene);
GenPgoSaveTilingKey(ss);
ss << GenSavePGOSearchTilingDataFunc(tiling);
ss << GenSavePGOConfigTilingDataFunc();
ss << GenPgoTilingSearchByCoreNum(fused_schedule_result, pgo_shape_dim, tiling, is_inductor_scene, core_num);
ss << GenPgoTilingSearchPGO(fused_schedule_result, pgo_shape_dim, tiling, is_inductor_scene, core_num);
ss << GenPgoTilingSearch(fused_schedule_result, pgo_shape_dim, tiling);
return ss.str();
}
std::string TilingLib::GenPgoAutofuseTiling(const ascir::FusedScheduledResult &fused_schedule_result,
codegen::PgoShapeStringStream &pgo_shape_dim, const std::string &tiling,
bool is_inductor_scene) const {
std::stringstream ss;
ss << "extern \"C\" int64_t AutofuseTilingWithConfig(const char *config_file, ";
ss << pgo_shape_dim.shape_dim_def.str();
ss << tiling << " *tiling, uint32_t *workspaceSize, uint32_t *blockDim,";
ss << " ResLimit *res_limit = nullptr, int32_t tiling_case_id = -1)" << std::endl;
ss << "{" << std::endl;
ss << " const ResLimit effective_res_limit = GetResLimit(res_limit);" << std::endl;
ss << " const ResLimit *limit = &effective_res_limit;" << std::endl;
ss << pgo_shape_dim.tiling_set_shape_dim.str();
ss << " tiling->set_block_dim(limit->aiv_num);" << std::endl;
if (is_inductor_scene) {
ss << " tiling->set_ub_size(limit->ub_size - 256);" << std::endl;
} else {
ss << " tiling->set_ub_size(limit->ub_size);" << std::endl;
}
if (!ascgen_utils::IsJustCubeFixpip(fused_schedule_result)) {
if (enable_autofuse_pgo_) {
ss << " auto pgo_tiling = *tiling;" << std::endl;
ss << " bool use_pgo_tiling = PGOGetTilingKey(config_file, pgo_tiling);" << std::endl;
ss << " if (use_pgo_tiling && (pgo_tiling.get_block_dim() == 0U || "
"pgo_tiling.get_block_dim() > limit->aiv_num)) {"
<< std::endl;
ss << " OP_LOGW(OP_NAME, \"Loaded PGO block_dim %u is outside core budget [1, %u].\", "
"pgo_tiling.get_block_dim(), limit->aiv_num);"
<< std::endl;
ss << " use_pgo_tiling = false;" << std::endl;
ss << " }" << std::endl;
ss << " if (use_pgo_tiling) {" << std::endl;
ss << " *tiling = pgo_tiling;" << std::endl;
if (codegen_func_ != nullptr) {
if (ascgen_utils::IsSingleGroup(fused_schedule_result)) {
ss << " optiling::EmitFinalTilingByCase(*tiling, tiling->get_block_dim(), \"pgo\", \"pgo\", 0U, -1);"
<< std::endl;
} else {
ss << " optiling::EmitFinalTilingForPgo(*tiling, tiling->get_block_dim());" << std::endl;
}
}
ss << " } else {" << std::endl;
ss << " if (!optiling::GetTiling(*tiling, tiling_case_id, nullptr)) {" << std::endl;
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
ss << " }" << std::endl;
} else {
ss << " (void)config_file;" << std::endl;
ss << " if (!optiling::GetTiling(*tiling, tiling_case_id, nullptr)) {" << std::endl;
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
}
ss << " *blockDim = tiling->get_block_dim();" << std::endl;
ss << " using namespace optiling;" << std::endl;
}
ss << " *workspaceSize = GetWorkspaceSize(*tiling);" << std::endl;
if (!is_inductor_scene) {
ss << " *workspaceSize += 16 * 1024 * 1024;" << std::endl;
}
ss << std::endl;
ss << " return 0;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
std::string TilingLib::GenProfilingAllTilingData(std::string tiling_data_list_name,
std::string tiling_data_perf_list_name,
const ascir::FusedScheduledResult &fused_schedule_result,
bool is_inductor_scene) const {
std::stringstream ss;
ss << " double out_cost = DBL_MAX;" << std::endl;
ss << " *workspaceSize = 0;" << std::endl;
ss << " std::vector<AutofuseTilingDataPerf> raw_search_candidates;" << std::endl;
ss << " for (const auto &tiling_data_item : " << tiling_data_list_name << ") {" << std::endl;
ss << " *workspaceSize = std::max(GetWorkspaceSize(tiling_data_item), *workspaceSize);" << std::endl;
ss << " AutofuseTilingDataPerf tiling_data_perf;" << std::endl;
ss << " tiling_data_perf.tiling_data = tiling_data_item;" << std::endl;
ss << " tiling_data_perf.best_perf = DBL_MAX;" << std::endl;
ss << " raw_search_candidates.push_back(tiling_data_perf);" << std::endl;
ss << " }" << std::endl;
if (!is_inductor_scene) {
ss << " *workspaceSize += 16 * 1024 * 1024;" << std::endl;
}
ss << " auto normalized_search_candidates = NormalizePgoMeasuredCandidates(std::move(raw_search_candidates));"
<< std::endl;
ss << " " << tiling_data_perf_list_name << ".insert(" << tiling_data_perf_list_name
<< ".end(), normalized_search_candidates.begin(), normalized_search_candidates.end());" << std::endl;
ss << " PgoConfig::Instance().batch_callback(" << PGOSearchFuncInputOutputCall(fused_schedule_result)
<< "stream, *workspaceSize, &" << tiling_data_perf_list_name << ");" << std::endl;
return ss.str();
}
std::string TilingLib::GenPgoTilingSearchByCoreNum(const ascir::FusedScheduledResult &fused_schedule_result,
codegen::PgoShapeStringStream &pgo_shape_dim,
const std::string &tiling, bool is_inductor_scene,
const std::string &core_num) const {
std::stringstream ss;
ss << "extern \"C\" int64_t PgoTilingSearchByCoreNum(char *search_file, char *config_file, ";
ss << pgo_shape_dim.shape_dim_def.str();
ss << tiling << " *tiling, uint32_t *workspaceSize, uint32_t *blockDim,";
ss << " ResLimit *res_limit = nullptr, ";
ss << PGOSearchFuncInputOutputDef(fused_schedule_result);
ss << "void *stream=nullptr, ProfilingCallback prof_callback=nullptr, ProfilingBatchCallback "
"prof_batch_callback=nullptr) {"
<< std::endl;
ss << " (void)prof_callback;" << std::endl;
ss << " (void)prof_batch_callback;" << std::endl;
ss << " const ResLimit effective_res_limit = GetResLimit(res_limit);" << std::endl;
ss << " const ResLimit *limit = &effective_res_limit;" << std::endl;
ss << pgo_shape_dim.tiling_set_shape_dim.str();
ss << " double best_perf = DBL_MAX;" << std::endl;
ss << " uint32_t max_block_dim = limit->aiv_num;" << std::endl;
ss << GenGetMaxBlockDimFromInput(core_num);
ss << " using namespace optiling;" << std::endl;
ss << " std::vector<AutofuseTilingData> tiling_data_list;" << std::endl;
ss << " std::vector<AutofuseTilingDataPerf> tiling_data_perf_list;" << std::endl;
ss << " double axeorder_cost = DBL_MAX;" << std::endl;
ss << " AutofuseTiling(";
ss << pgo_shape_dim.shape_dim_use.str();
ss << GenGetAutoFuseTilingInput(is_inductor_scene);
ss << " PgoConfig::Instance().single_callback(";
ss << PGOSearchFuncInputOutputCall(fused_schedule_result);
ss << "stream, *workspaceSize, tiling, &axeorder_cost);" << std::endl;
ss << " AutofuseTilingDataPerf tiling_data_axereorder_perf;" << std::endl;
ss << " tiling_data_axereorder_perf.tiling_data = *tiling;" << std::endl;
ss << " tiling_data_axereorder_perf.best_perf = axeorder_cost;" << std::endl;
ss << " tiling_data_perf_list.push_back(tiling_data_axereorder_perf);" << std::endl;
ss << " PgoConfig::Instance().need_change_solver_run = true;" << std::endl;
ss << " PgoConfig::Instance().pgo_threshold_index = 0;" << std::endl;
ss << " while (PgoConfig::Instance().pgo_threshold_index < PgoConfig::Instance().pgo_threshold_list_size) {"
<< std::endl;
ss << " if (!optiling::PGOByCoreNumSearchTilingKey(tiling_data_list, tiling, max_block_dim)) {" << std::endl;
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
ss << " PgoConfig::Instance().pgo_threshold_index++;" << std::endl;
ss << " }" << std::endl;
ss << GenProfilingAllTilingData("tiling_data_list", "tiling_data_perf_list", fused_schedule_result,
is_inductor_scene);
ss << " best_perf = DBL_MAX;" << std::endl;
ss << " SavePGOSearchTilingData(search_file, tiling_data_perf_list);" << std::endl;
ss << " SavePGOConfigTilingData(config_file, tiling_data_perf_list, best_perf);" << std::endl;
ss << " return 0;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
std::string TilingLib::GenPgoTilingSearch(const ascir::FusedScheduledResult &fused_schedule_result,
codegen::PgoShapeStringStream &pgo_shape_dim,
const std::string &tiling) const {
std::stringstream ss;
ss << "extern \"C\" int64_t PgoTilingSearch(char *search_file, char *config_file, ";
ss << pgo_shape_dim.shape_dim_def.str();
ss << tiling << " *tiling, uint32_t *workspaceSize, uint32_t *blockDim,";
ss << " ResLimit *res_limit = nullptr, ";
ss << PGOSearchFuncInputOutputDef(fused_schedule_result);
ss << "void *stream=nullptr, ProfilingCallback prof_callback=nullptr, ProfilingBatchCallback "
"prof_batch_callback=nullptr) {"
<< std::endl;
ss << " const char* var = std::getenv(\"AUTOFUSE_DFX_FLAGS\");" << std::endl;
ss << " if ((var != nullptr) && (std::string(var).find(\"autofuse_pgo_algo=pruning\") != std::string::npos)) {"
<< std::endl;
ss << " PgoConfig::Instance().pgo_algorithm = 0;" << std::endl;
ss << " } else {" << std::endl;
ss << " PgoConfig::Instance().pgo_algorithm = 1;" << std::endl;
ss << " }" << std::endl;
ss << " PgoConfig::Instance().single_callback = prof_callback;" << std::endl;
ss << " PgoConfig::Instance().batch_callback = prof_batch_callback;" << std::endl;
ss << " if (PgoConfig::Instance().pgo_algorithm == 0) {" << std::endl;
ss << " PgoTilingSearchPGO(search_file, config_file, " << pgo_shape_dim.shape_dim_use.str()
<< " tiling, workspaceSize, blockDim, res_limit, ";
ss << PGOSearchFuncInputOutputCall(fused_schedule_result)
<< "stream, PgoConfig::Instance().single_callback, PgoConfig::Instance().batch_callback);" << std::endl;
ss << " } else if (PgoConfig::Instance().pgo_algorithm == 1) {" << std::endl;
ss << " PgoTilingSearchByCoreNum(search_file, config_file, " << pgo_shape_dim.shape_dim_use.str()
<< " tiling, workspaceSize, blockDim, res_limit, ";
ss << PGOSearchFuncInputOutputCall(fused_schedule_result)
<< "stream, PgoConfig::Instance().single_callback, PgoConfig::Instance().batch_callback);" << std::endl;
ss << " }" << std::endl;
ss << " return 0;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
std::string TilingLib::GenGetMaxBlockDimFromInput(const std::string &core_num) const {
std::stringstream ss;
if (std::stoi(core_num) != 0) {
ss << " auto max_core_num = " << core_num << ";" << std::endl;
ss << " tiling->set_block_dim(max_core_num);" << std::endl;
ss << " max_block_dim = max_core_num;" << std::endl;
}
return ss.str();
}
std::string TilingLib::GenGetAutoFuseTilingInput(bool is_inductor_scene) const {
std::stringstream ss;
ss << "tiling, workspaceSize, blockDim, ";
if (is_inductor_scene) {
ss << "res_limit);" << std::endl;
} else {
ss << "limit->aiv_num, limit->ub_size - 256);" << std::endl;
}
return ss.str();
}
void TilingLib::GenPgoTilingKeySearch(const ascir::FusedScheduledResult &fused_schedule_result,
std::stringstream &ss) const {
if (ascgen_utils::IsSingleGroup(fused_schedule_result)) {
ss << " // 不使用,仅保持接口一致" << std::endl;
ss << " std::unordered_map<int64_t, uint64_t> workspace_map;" << std::endl;
ss << " if (!optiling::PGOSearchTilingKey(tiling_data_list, *tiling, -1, tiling, "
<< PGOSearchFuncInputOutputCall(fused_schedule_result) << "stream, *workspaceSize, best_perf, workspace_map)) {"
<< std::endl;
} else {
ss << " if (!optiling::PGOSearchTilingKey(tiling_data_list, *tiling, -1, tiling, "
<< PGOSearchFuncInputOutputCall(fused_schedule_result) << "stream, *workspaceSize, best_perf)) {" << std::endl;
}
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
}
std::string TilingLib::GenPgoTilingSearchPGO(const ascir::FusedScheduledResult &fused_schedule_result,
codegen::PgoShapeStringStream &pgo_shape_dim, const std::string &tiling,
bool is_inductor_scene, const std::string &core_num) const {
std::stringstream ss;
ss << "extern \"C\" int64_t PgoTilingSearchPGO(char *search_file, char *config_file, "
<< pgo_shape_dim.shape_dim_def.str() << tiling << " *tiling, uint32_t *workspaceSize, uint32_t *blockDim,"
<< " ResLimit *res_limit = nullptr, " << PGOSearchFuncInputOutputDef(fused_schedule_result)
<< "void *stream=nullptr, ProfilingCallback prof_callback=nullptr, ProfilingBatchCallback "
<< "prof_batch_callback=nullptr) {" << std::endl;
ss << " (void)prof_callback;" << std::endl;
ss << " (void)prof_batch_callback;" << std::endl;
ss << " const ResLimit effective_res_limit = GetResLimit(res_limit);" << std::endl;
ss << " const ResLimit *limit = &effective_res_limit;" << std::endl;
ss << " std::vector<AutofuseTilingDataPerf> tiling_data_list;" << std::endl;
ss << pgo_shape_dim.tiling_set_shape_dim.str();
ss << " double best_perf = DBL_MAX;" << std::endl;
ss << " uint32_t max_block_dim = limit->aiv_num;" << std::endl;
ss << GenGetMaxBlockDimFromInput(core_num);
ss << " AutofuseTiling(" << pgo_shape_dim.shape_dim_use.str() << GenGetAutoFuseTilingInput(is_inductor_scene);
ss << " PgoConfig::Instance().single_callback(" << PGOSearchFuncInputOutputCall(fused_schedule_result)
<< "stream, *workspaceSize, tiling, &best_perf);" << std::endl;
ss << " if (optiling::IsEqual(best_perf, DBL_MAX)) {" << std::endl;
ss << " OP_LOGE(OP_NAME, \"axesreorder solution get perf failed %lf\", best_perf);" << std::endl;
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
ss << " AutofuseTilingDataPerf tiling_perf;" << std::endl;
ss << " tiling_perf.tiling_data = *tiling;" << std::endl;
ss << " tiling_perf.best_perf = best_perf;" << std::endl;
ss << " tiling_data_list.push_back(tiling_perf);" << std::endl;
ss << " OP_LOGD(OP_NAME, \"axesreorder solution base perf is %lf\", best_perf);" << std::endl;
ss << " tiling->set_block_dim(max_block_dim);" << std::endl;
GenPgoTilingKeySearch(fused_schedule_result, ss);
ss << " if (optiling::IsEqual(best_perf, DBL_MAX)) {" << std::endl;
ss << " OP_LOGE(OP_NAME, \"pgo solution get perf failed %lf\", best_perf);" << std::endl;
ss << " return -1;" << std::endl;
ss << " }" << std::endl;
ss << " SavePGOSearchTilingData(search_file, tiling_data_list);" << std::endl;
ss << " SavePGOConfigTilingData(config_file, tiling_data_list, best_perf);" << std::endl;
ss << " OP_LOGD(OP_NAME, \"pgo solution best perf is %lf\", best_perf);" << std::endl;
ss << std::endl;
ss << " return 0;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
std::string TilingLib::GenGetResLimitStru(void) const {
std::stringstream ss;
ss << "struct ResLimit {" << std::endl;
ss << " uint32_t valid_num = 0;" << std::endl;
ss << " uint32_t aiv_num = 0;" << std::endl;
ss << " uint32_t aic_num = 0;" << std::endl;
ss << " uint32_t ub_size = 0;" << std::endl;
ss << " uint32_t resv[10];" << std::endl;
ss << "};" << std::endl;
ge::PlatformInfo platform_info;
GE_ASSERT_SUCCESS(ge::PlatformContext::GetInstance().GetPlatformInfo(platform_info));
ss << "constexpr ResLimit g_no_limit_res = {1, " << platform_info.aiv_num << ", 0, " << platform_info.ub_size
<< ", {}};" << std::endl;
ss << "inline ResLimit GetResLimit(const ResLimit *res_limit) {" << std::endl;
ss << " ResLimit limit = g_no_limit_res;" << std::endl;
ss << " if (res_limit == nullptr) {" << std::endl;
ss << " return limit;" << std::endl;
ss << " }" << std::endl;
ss << " if (res_limit->valid_num > 0U) { limit.valid_num = res_limit->valid_num; }" << std::endl;
ss << " if (res_limit->aiv_num > 0U) { limit.aiv_num = res_limit->aiv_num; }" << std::endl;
ss << " if (res_limit->aic_num > 0U) { limit.aic_num = res_limit->aic_num; }" << std::endl;
ss << " if (res_limit->ub_size > 0U) { limit.ub_size = res_limit->ub_size; }" << std::endl;
ss << " for (uint32_t i = 0U; i < 10U; ++i) {" << std::endl;
ss << " if (res_limit->resv[i] > 0U) { limit.resv[i] = res_limit->resv[i]; }" << std::endl;
ss << " }" << std::endl;
ss << " return limit;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
bool TilingLib::IsMixKernelTaskType(const ascir::FusedScheduledResult &fused_schedule_result) const {
return fused_schedule_result.workspace_nodes.size() != 0;
}
std::string TilingLib::GenPGOGetTilingKey(const std::string tiling) const {
std::stringstream ss;
ss << "bool PGOGetTilingKey(const char *config_file_path, " << tiling << " &tiling_data) {" << std::endl;
ss << " OP_LOGD(OP_NAME, \"PGOGetTilingKey from file:%s.\", config_file_path);" << std::endl;
ss << " static int best_config = 0;" << std::endl;
ss << " static " + tiling + " best_tiling;" << std::endl;
ss << " if (best_config == 0) {" << std::endl;
ss << " std::ifstream config_file(config_file_path);" << std::endl;
ss << " if (!config_file.is_open()) {" << std::endl;
ss << " OP_LOGD(OP_NAME, \"failed to open or not exist: %s.\", config_file_path);" << std::endl;
ss << " return false;" << std::endl;
ss << " }" << std::endl;
ss << " OP_LOGD(OP_NAME, \"[Start to use tiling result]: %s.\", config_file_path);" << std::endl;
ss << " std::string line;" << std::endl;
ss << " // first line: 0:read every time; 1:read first time" << std::endl;
ss << " std::getline(config_file, line);" << std::endl;
ss << " std::istringstream iss0(line);" << std::endl;
ss << " int flag = -1;" << std::endl;
ss << " if (!(iss0 >> flag) || (flag != 0 && flag != 1)) {" << std::endl;
ss << " OP_LOGW(OP_NAME, \"Invalid PGO config flag.\");" << std::endl;
ss << " return false;" << std::endl;
ss << " }" << std::endl;
ss << " OP_LOGD(OP_NAME, \"best_config %d.\", flag);" << std::endl;
ss << " // second line: tiling_data dumped as int32 decimals, space-separated" << std::endl;
ss << " std::getline(config_file, line);" << std::endl;
ss << " if (line.find('#') != std::string::npos) {" << std::endl;
ss << " line = line.substr(0, line.find('#'));" << std::endl;
ss << " }" << std::endl;
ss << " std::istringstream iss1(line);" << std::endl;
ss << " std::vector<int32_t> tiling_i32;" << std::endl;
ss << " tiling_i32.reserve((sizeof(tiling_data) + sizeof(int32_t) - 1) / sizeof(int32_t));" << std::endl;
ss << " int64_t tmp = 0;" << std::endl;
ss << " while (iss1 >> tmp) {" << std::endl;
ss << " tiling_i32.push_back(static_cast<int32_t>(tmp));" << std::endl;
ss << " }" << std::endl;
ss << " const size_t expect_num = (sizeof(tiling_data) + sizeof(int32_t) - 1) / sizeof(int32_t);" << std::endl;
ss << " if (!iss1.eof() || tiling_i32.size() != expect_num) {" << std::endl;
ss << " OP_LOGW(OP_NAME, \"Invalid PGO tiling data length.\");" << std::endl;
ss << " return false;" << std::endl;
ss << " }" << std::endl;
ss << " if (memcpy_s(&tiling_data, sizeof(tiling_data), tiling_i32.data(), sizeof(tiling_data)) != EOK) {"
<< std::endl;
ss << " OP_LOGW(OP_NAME, \"Failed to load PGO tiling data.\");" << std::endl;
ss << " return false;" << std::endl;
ss << " }" << std::endl;
ss << " config_file.close();" << std::endl;
ss << " if (flag == 1) {" << std::endl;
ss << " best_tiling = tiling_data;" << std::endl;
ss << " best_config = flag;" << std::endl;
ss << " }" << std::endl;
ss << " } else {" << std::endl;
ss << " tiling_data = best_tiling;" << std::endl;
ss << " }" << std::endl;
ss << " return true;" << std::endl;
ss << "}" << std::endl;
ss << "" << std::endl;
return ss.str();
}
std::string TilingLib::GenSavePGOSearchTilingDataFunc(const std::string tiling) const {
std::stringstream ss;
ss << "void SavePGOSearchTilingData(char *search_file, std::vector<" << tiling << "Perf> &tiling_data_list, "
<< "std::ios::openmode mode = std::ios::out) {" << std::endl;
ss << " OP_LOGI(OP_NAME, \"SavePGOSearchTilingData to file:%s.\", search_file);" << std::endl;
ss << " std::ofstream out_file(search_file, mode);" << std::endl;
ss << " if (!out_file.is_open()) {" << std::endl;
ss << " OP_LOGE(OP_NAME, \"Failed to open file:%s.\", search_file);" << std::endl;
ss << " return;" << std::endl;
ss << " }" << std::endl;
ss << " for (auto item = tiling_data_list.rbegin(); item != tiling_data_list.rend(); ++item) {" << std::endl;
ss << " PgoSaveTilingKey(item->tiling_data, item->best_perf, out_file);" << std::endl;
ss << " }" << std::endl;
ss << " out_file.close();" << std::endl;
ss << std::endl;
ss << " return;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
std::string TilingLib::GenSavePGOConfigTilingDataFunc() const {
std::stringstream ss;
ss << "void SavePGOConfigTilingData(char *file, std::vector<AutofuseTilingDataPerf> &tiling_data_list, "
<< "double best_perf, std::ios::openmode mode = std::ios::out) {" << std::endl;
ss << " OP_LOGI(OP_NAME, \"SavePGOConfigTilingData to file:%s.\", file);" << std::endl;
ss << " std::ofstream out_file(file, mode);" << std::endl;
ss << " if (!out_file.is_open()) {" << std::endl;
ss << " OP_LOGE(OP_NAME, \"Failed to open file:%s.\", file);" << std::endl;
ss << " return;" << std::endl;
ss << " }" << std::endl;
ss << " if (PgoConfig::Instance().pgo_algorithm == 1) {" << std::endl;
ss << " for (auto item : tiling_data_list) {" << std::endl;
ss << " if (item.best_perf < best_perf) {" << std::endl;
ss << " best_perf = item.best_perf;" << std::endl;
ss << " }" << std::endl;
ss << " }" << std::endl;
ss << " }" << std::endl;
ss << " out_file << \"1\" << std::endl;" << std::endl;
ss << " for (auto item = tiling_data_list.rbegin(); item != tiling_data_list.rend(); ++item) {" << std::endl;
ss << " if (optiling::IsEqual(item->best_perf, best_perf)) {" << std::endl;
ss << " PgoSaveTilingKey(item->tiling_data, item->best_perf, out_file);" << std::endl;
ss << " break;" << std::endl;
ss << " }" << std::endl;
ss << " }" << std::endl;
ss << " out_file.close();" << std::endl;
ss << std::endl;
ss << " return;" << std::endl;
ss << "}" << std::endl;
return ss.str();
}
}