handle backend cleanup errors and use 256 MiB residency blocks

This commit is contained in:
leejet 2026-09-13 16:56:04 +08:00
parent d9ddfa0d4b
commit da4e841ba1
6 changed files with 32 additions and 7 deletions

View File

@ -294,6 +294,8 @@ endif()
if(MSVC) if(MSVC)
target_compile_options(${SD_LIB} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/bigobj>) target_compile_options(${SD_LIB} PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/bigobj>)
# ggml backends can throw C++ exceptions through their C API.
target_compile_options(${SD_LIB} PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CXX_COMPILER_ID:MSVC>>:/EHsc->)
endif() endif()
if(APPLE) if(APPLE)

View File

@ -2,12 +2,14 @@
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <exception>
#include <map> #include <map>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include "core/ggml_extend_backend.h" #include "core/ggml_extend_backend.h"
#include "core/ggml_graph_cut.h" #include "core/ggml_graph_cut.h"
#include "core/util.h"
#include "ggml-cpu.h" #include "ggml-cpu.h"
#include "ggml/src/ggml-impl.h" #include "ggml/src/ggml-impl.h"
@ -228,11 +230,23 @@ namespace sd {
} }
} }
void ComputeWorkspace::segment_end() { bool ComputeWorkspace::segment_end() noexcept {
if (active_) { if (!active_) {
synchronize(); return true;
active_ = false;
} }
// Outer cleanup guards must not retry a failed backend submission.
active_ = false;
try {
synchronize();
return true;
} catch (const std::exception& error) {
LOG_ERROR("%s workspace synchronization failed during segment cleanup: %s",
ggml_backend_name(backend_), error.what());
} catch (...) {
LOG_ERROR("%s workspace synchronization failed during segment cleanup: unknown exception",
ggml_backend_name(backend_));
}
return false;
} }
bool ComputeWorkspace::release() { bool ComputeWorkspace::release() {

View File

@ -51,7 +51,7 @@ namespace sd {
const std::function<ggml_backend_t(const ggml_tensor*)>& external_backend, const std::function<ggml_backend_t(const ggml_tensor*)>& external_backend,
const AssignNodes& assign_nodes); const AssignNodes& assign_nodes);
void synchronize() const; void synchronize() const;
void segment_end(); bool segment_end() noexcept;
bool release(); bool release();
bool active() const { return active_; } bool active() const { return active_; }
ggml_backend_sched_t scheduler() const { return scheduler_; } ggml_backend_sched_t scheduler() const { return scheduler_; }

View File

@ -660,7 +660,13 @@ void SDBackendAssignment::set_module(SDBackendModule module, const std::string&
} }
void SDBackendHandleDeleter::operator()(ggml_backend_t backend) const { void SDBackendHandleDeleter::operator()(ggml_backend_t backend) const {
ggml_backend_free(backend); try {
ggml_backend_free(backend);
} catch (const std::exception& error) {
LOG_ERROR("backend cleanup failed: %s", error.what());
} catch (...) {
LOG_ERROR("backend cleanup failed: unknown exception");
}
} }
SDBackendManager::~SDBackendManager() { SDBackendManager::~SDBackendManager() {

View File

@ -964,6 +964,9 @@ std::optional<Tensor<float>> GGMLRunner::execute_graph(ggml_cgraph* graph, int n
} }
} }
} }
if (!workspace_.segment_end()) {
return fail_segment("workspace synchronization");
}
// Final outputs and their callbacks may still be views of consumed cuts. // Final outputs and their callbacks may still be views of consumed cuts.
cut_cache_.prune(segment.future_cut_names); cut_cache_.prune(segment.future_cut_names);
} }

View File

@ -31,7 +31,7 @@ public:
}; };
private: private:
static constexpr size_t MAX_RESIDENCY_BLOCK_BYTES = 64ULL * 1024ULL * 1024ULL; static constexpr size_t MAX_RESIDENCY_BLOCK_BYTES = 256ULL * 1024ULL * 1024ULL;
struct TensorState { struct TensorState {
std::string name; std::string name;