diff --git a/CMakeLists.txt b/CMakeLists.txt index 04036ade..389c4d4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -294,6 +294,8 @@ endif() if(MSVC) target_compile_options(${SD_LIB} PRIVATE $<$:/bigobj>) + # ggml backends can throw C++ exceptions through their C API. + target_compile_options(${SD_LIB} PRIVATE $<$,$>:/EHsc->) endif() if(APPLE) diff --git a/src/core/compute_workspace.cpp b/src/core/compute_workspace.cpp index a40e2dbd..58e85fa6 100644 --- a/src/core/compute_workspace.cpp +++ b/src/core/compute_workspace.cpp @@ -2,12 +2,14 @@ #include #include +#include #include #include #include #include "core/ggml_extend_backend.h" #include "core/ggml_graph_cut.h" +#include "core/util.h" #include "ggml-cpu.h" #include "ggml/src/ggml-impl.h" @@ -228,11 +230,23 @@ namespace sd { } } - void ComputeWorkspace::segment_end() { - if (active_) { - synchronize(); - active_ = false; + bool ComputeWorkspace::segment_end() noexcept { + if (!active_) { + return true; } + // 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() { diff --git a/src/core/compute_workspace.h b/src/core/compute_workspace.h index 7e73c23e..fcf14b85 100644 --- a/src/core/compute_workspace.h +++ b/src/core/compute_workspace.h @@ -51,7 +51,7 @@ namespace sd { const std::function& external_backend, const AssignNodes& assign_nodes); void synchronize() const; - void segment_end(); + bool segment_end() noexcept; bool release(); bool active() const { return active_; } ggml_backend_sched_t scheduler() const { return scheduler_; } diff --git a/src/core/ggml_extend_backend.cpp b/src/core/ggml_extend_backend.cpp index 9c4cfa42..1cfaaa48 100644 --- a/src/core/ggml_extend_backend.cpp +++ b/src/core/ggml_extend_backend.cpp @@ -660,7 +660,13 @@ void SDBackendAssignment::set_module(SDBackendModule module, const std::string& } 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() { diff --git a/src/core/ggml_runner.cpp b/src/core/ggml_runner.cpp index 82fff07a..65ed8b87 100644 --- a/src/core/ggml_runner.cpp +++ b/src/core/ggml_runner.cpp @@ -964,6 +964,9 @@ std::optional> 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. cut_cache_.prune(segment.future_cut_names); } diff --git a/src/model_manager.h b/src/model_manager.h index ccd7a5e3..76777eda 100644 --- a/src/model_manager.h +++ b/src/model_manager.h @@ -31,7 +31,7 @@ public: }; 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 { std::string name;