[backend]完善异步执行的超时切断机制

This commit is contained in:
Lixuanwang
2025-08-18 22:50:14 +08:00
parent 0720a622c1
commit babb576317
3 changed files with 44 additions and 12 deletions

View File

@@ -9,6 +9,9 @@
#include <sstream> #include <sstream>
#include <future> #include <future>
#include <chrono> #include <chrono>
#include <atomic>
#include <memory>
#include <thread>
#include <iostream> #include <iostream>
namespace sysy { namespace sysy {
@@ -233,23 +236,46 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
scheduler.runOnMachineFunction(mfunc.get()); scheduler.runOnMachineFunction(mfunc.get());
// 阶段 3: 物理寄存器分配 (Register Allocation) // 阶段 3: 物理寄存器分配 (Register Allocation)
bool allocation_succeeded = false; bool allocation_succeeded = false;
// 尝试迭代图着色 (IRC) // 尝试迭代图着色 (IRC)
if (!irc_failed) { if (!irc_failed) {
if (DEBUG) std::cerr << "Attempting Register Allocation with Iterated Register Coloring (IRC)...\n"; if (DEBUG) std::cerr << "Attempting Register Allocation with Iterated Register Coloring (IRC)...\n";
RISCv64RegAlloc irc_alloc(mfunc.get()); RISCv64RegAlloc irc_alloc(mfunc.get());
if (irc_alloc.run()) { auto stop_flag = std::make_shared<std::atomic<bool>>(false);
auto future = std::async(std::launch::async, &RISCv64RegAlloc::run, &irc_alloc, stop_flag);
std::future_status status = future.wait_for(std::chrono::seconds(25));
bool success_irc = false;
if (status == std::future_status::ready) {
try {
if (future.get()) {
success_irc = true;
} else {
std::cerr << "Warning: IRC explicitly returned failure for function '" << func->getName() << "'.\n";
}
} catch (const std::exception& e) {
std::cerr << "Error: IRC allocation threw an exception: " << e.what() << std::endl;
}
} else if (status == std::future_status::timeout) {
std::cerr << "Warning: IRC allocation timed out after 25 seconds. Requesting cancellation...\n";
stop_flag->store(true);
try {
future.get();
} catch (const std::exception& e) {
std::cerr << "Exception occurred during IRC thread shutdown after timeout: " << e.what() << std::endl;
}
}
if (success_irc) {
allocation_succeeded = true; allocation_succeeded = true;
if (DEBUG) std::cerr << "IRC allocation succeeded.\n"; if (DEBUG) std::cerr << "IRC allocation succeeded.\n";
} else { } else {
std::cerr << "Warning: IRC failed for function '" << func->getName() std::cerr << "Info: Blacklisting IRC for subsequent functions and falling back.\n";
<< "'. Blacklisting IRC for subsequent functions and falling back.\n"; irc_failed = true;
irc_failed = true; // 拉黑IRC后续函数不再尝试
} }
} }
// 尝试简单图着色 (SGC) 并设置超时 // 尝试简单图着色 (SGC)
if (!allocation_succeeded) { if (!allocation_succeeded) {
// 如果是从IRC失败回退过来的需要重新创建干净的mfunc和ISel // 如果是从IRC失败回退过来的需要重新创建干净的mfunc和ISel
RISCv64ISel isel_for_sgc; RISCv64ISel isel_for_sgc;
@@ -266,7 +292,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
{ {
RISCv64SimpleRegAlloc sgc_alloc(mfunc.get()); RISCv64SimpleRegAlloc sgc_alloc(mfunc.get());
auto future = std::async(std::launch::async, &RISCv64SimpleRegAlloc::run, &sgc_alloc); auto future = std::async(std::launch::async, &RISCv64SimpleRegAlloc::run, &sgc_alloc);
std::future_status status = future.wait_for(std::chrono::seconds(20)); std::future_status status = future.wait_for(std::chrono::seconds(25));
if (status == std::future_status::ready) { if (status == std::future_status::ready) {
try { try {
@@ -287,7 +313,7 @@ std::string RISCv64CodeGen::function_gen(Function* func) {
} }
} }
// 策略三:如果以上所有策略都失败了,则使用基本块分配器 (BBA) // 如果都失败了,则使用基本块分配器 (BBA)
if (!allocation_succeeded) { if (!allocation_succeeded) {
// 为BBA准备干净的mfunc和ISel // 为BBA准备干净的mfunc和ISel
std::cerr << "Info: Resetting MachineFunction for BBA fallback.\n"; std::cerr << "Info: Resetting MachineFunction for BBA fallback.\n";

View File

@@ -7,6 +7,7 @@
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <atomic>
namespace sysy { namespace sysy {
@@ -47,7 +48,7 @@ RISCv64RegAlloc::RISCv64RegAlloc(MachineFunction* mfunc)
} }
// 主入口: 迭代运行分配算法直到无溢出 // 主入口: 迭代运行分配算法直到无溢出
bool RISCv64RegAlloc::run() { bool RISCv64RegAlloc::run(std::shared_ptr<std::atomic<bool>> stop_flag) {
if (DEBUG) std::cerr << "===== LLIR Before Running Graph Coloring Register Allocation " << MFunc->getName() << " =====\n"; if (DEBUG) std::cerr << "===== LLIR Before Running Graph Coloring Register Allocation " << MFunc->getName() << " =====\n";
std::stringstream ss_before_reg_alloc; std::stringstream ss_before_reg_alloc;
if (DEBUG) { if (DEBUG) {
@@ -68,6 +69,11 @@ bool RISCv64RegAlloc::run() {
break; break;
} else { } else {
rewriteProgram(); rewriteProgram();
if (stop_flag && stop_flag->load()) {
// 如果从外部接收到停止信号
std::cerr << "Info: IRC allocation cancelled due to timeout.\n";
return false; // 提前退出,并返回失败
}
if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n"; if (DEBUG) std::cerr << "--- Spilling detected, re-running allocation (iteration " << iteration << ") ---\n";
if (iteration >= MAX_ITERATIONS) { if (iteration >= MAX_ITERATIONS) {

View File

@@ -20,7 +20,7 @@ public:
RISCv64RegAlloc(MachineFunction* mfunc); RISCv64RegAlloc(MachineFunction* mfunc);
// 模块主入口 // 模块主入口
bool run(); bool run(std::shared_ptr<std::atomic<bool>> stop_flag);
private: private:
// 类型定义与Python版本对应 // 类型定义与Python版本对应