mirror of
https://github.com/leejet/stable-diffusion.cpp.git
synced 2026-11-12 11:56:36 +00:00
refactor: consolidate graph helpers in sd.cpp
This commit is contained in:
1 parent
6cfc3572f7
commit
ee12f0ea97
8 files changed
+59
-75
No files matched your search
+5
-4
@@ -33,8 +33,9 @@ cmake --build build-upstream --config Release
|
||||
```
|
||||
|
||||
Both patched and upstream builds use the selected library and matching private
|
||||
headers for backend integration. Backend options such as `-DSD_CUDA=ON` apply
|
||||
to the selected tree as usual.
|
||||
headers for application graph helpers and backend integration. The generic
|
||||
operator registration API remains in `ggml-ext.h`. Backend options such as
|
||||
`-DSD_CUDA=ON` apply to the selected tree as usual.
|
||||
|
||||
`SD_USE_UPSTREAM_GGML` defaults to `OFF`, which enables the patched GGML
|
||||
extensions. Set it to `ON` when using upstream GGML; it selects the compatibility
|
||||
@@ -52,8 +53,8 @@ quantization types remain available, subject to backend operator support.
|
||||
|
||||
`SD_USE_SYSTEM_GGML=ON` instead links an installed GGML CMake package, located
|
||||
with `ggml_DIR` or `CMAKE_PREFIX_PATH`. An installed patched package must include
|
||||
the extension and graph APIs. Set `SD_GGML_SOURCE_DIR` to its matching source
|
||||
tree for private backend headers, including CUDA/HIP/MUSA vendor headers.
|
||||
the extension API. Set `SD_GGML_SOURCE_DIR` to its matching source tree for
|
||||
private graph and backend headers, including CUDA/HIP/MUSA vendor headers.
|
||||
The installed library must use the same ABI settings as sd.cpp,
|
||||
including `GGML_MAX_NAME`. For an upstream package, also set
|
||||
`SD_USE_UPSTREAM_GGML=ON` and point `SD_GGML_SOURCE_DIR` to its matching source
|
||||
|
||||
+10
-14
@@ -448,22 +448,18 @@ kernel compiled for SM80 or newer. CPU, HIP, MUSA, and Vulkan do not advertise
|
||||
support. ggml no longer contains a Sol-Attn opcode, constructor, allocation rule,
|
||||
or backend kernel.
|
||||
|
||||
## Public graph access
|
||||
## Internal graph access
|
||||
|
||||
`ggml-graph.h` exposes leaf enumeration, append-only leaf construction, recorded
|
||||
use counts, mapped inference-graph copying, use-count copying for segments, and
|
||||
backend execution of a node range. Mapped copies retain node order and consumer
|
||||
counts from the original graph, including consumers outside a graph view. The
|
||||
caller owns tensor copies and remaps their storage and edges; invalid mappings
|
||||
leave the destination graph unchanged. Range execution uses already allocated
|
||||
tensors and retains the original graph's consumer counts.
|
||||
`src/core/ggml_compat.cpp` uses `ggml-impl.h` for leaf enumeration, graph copying,
|
||||
use-count preservation and range execution. Patched and upstream builds share
|
||||
this implementation; ggml does not expose a separate public graph API for these
|
||||
application helpers. Mapped copies retain node order and consumer counts,
|
||||
including consumers outside a graph view. Invalid mappings leave the destination
|
||||
unchanged. Workspace measurement, graph cuts and evaluation callbacks use these
|
||||
helpers.
|
||||
|
||||
Workspace measurement, graph cuts, and evaluation callbacks use these APIs.
|
||||
Backend extensions require matching private headers. Compatibility with an
|
||||
upstream ggml lacking this header is isolated in `src/core/ggml_compat.cpp`; that
|
||||
optional build still requires matching upstream private headers. The compatibility
|
||||
layer also retains the workaround for old Metal backends wrapping failed host
|
||||
mappings. The patched Metal backend returns null directly when mapping fails.
|
||||
The compatibility layer also retains the workaround for old Metal backends
|
||||
wrapping failed host mappings. The patched Metal backend returns null directly.
|
||||
|
||||
Vulkan command recording services are declared in the private
|
||||
`ggml/src/ggml-ext-vulkan.h`. Pipeline ownership, submission and synchronization
|
||||
|
||||
+1
-1
Submodule ggml updated: 6eca604461...18ffcfde29.
@@ -69,7 +69,7 @@ namespace sd {
|
||||
|
||||
bool ComputeWorkspace::allocate(ggml_cgraph* graph, const AssignNodes& assign_nodes) {
|
||||
GGML_ASSERT(!active_);
|
||||
const size_t capacity = static_cast<size_t>(ggml_graph_n_nodes(graph) + ggml_graph_n_leafs(graph)) + 8;
|
||||
const size_t capacity = static_cast<size_t>(ggml_graph_n_nodes(graph) + sd_ggml_graph_n_leafs(graph)) + 8;
|
||||
if (scheduler_ == nullptr || capacity > scheduler_capacity_) {
|
||||
release();
|
||||
scheduler_ = make_scheduler(capacity);
|
||||
@@ -104,8 +104,8 @@ namespace sd {
|
||||
for (int i = 0; i < ggml_graph_n_nodes(graph); ++i) {
|
||||
visit(ggml_graph_node(graph, i));
|
||||
}
|
||||
for (int i = 0; i < ggml_graph_n_leafs(graph); ++i) {
|
||||
visit(ggml_graph_leaf(graph, i));
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(graph); ++i) {
|
||||
visit(sd_ggml_graph_leaf(graph, i));
|
||||
}
|
||||
for (size_t i = 0; i < tensors.size(); ++i) {
|
||||
visit(tensors[i]->view_src);
|
||||
@@ -121,7 +121,7 @@ namespace sd {
|
||||
key.insert(key.end(), bytes, bytes + sizeof(value));
|
||||
};
|
||||
append(ggml_graph_n_nodes(graph));
|
||||
append(ggml_graph_n_leafs(graph));
|
||||
append(sd_ggml_graph_n_leafs(graph));
|
||||
for (auto tensor : tensors) {
|
||||
append(tensor);
|
||||
append(tensor->type);
|
||||
@@ -150,7 +150,7 @@ namespace sd {
|
||||
const auto alignment_offset = reinterpret_cast<uintptr_t>(tensor->data) % ggml_backend_get_alignment(external);
|
||||
append(alignment_offset);
|
||||
}
|
||||
const int32_t uses = ggml_graph_use_count(graph, tensor);
|
||||
const int32_t uses = sd_ggml_graph_use_count(graph, tensor);
|
||||
append(uses);
|
||||
}
|
||||
// Match the full allocation metadata, including topology and external placement.
|
||||
@@ -197,7 +197,7 @@ namespace sd {
|
||||
const auto found = mapped.find(tensor);
|
||||
return found == mapped.end() ? nullptr : found->second;
|
||||
};
|
||||
GGML_ASSERT(ggml_graph_cpy_mapped(graph, copy_graph, map_tensor, &copies));
|
||||
GGML_ASSERT(sd_ggml_graph_cpy_mapped(graph, copy_graph, map_tensor, &copies));
|
||||
Measurement result;
|
||||
auto scheduler = make_scheduler(graph_size);
|
||||
if (scheduler != nullptr) {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "core/ggml_compat.h"
|
||||
#include "core/ggml_extend_backend.h"
|
||||
|
||||
#ifdef SD_GGML_GRAPH_COMPAT
|
||||
// Upstream ggml still requires its private graph layout for these operations.
|
||||
#include "ggml-impl.h"
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -10,11 +8,11 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
int ggml_graph_n_leafs(const ggml_cgraph* graph) {
|
||||
int sd_ggml_graph_n_leafs(const ggml_cgraph* graph) {
|
||||
return graph->n_leafs;
|
||||
}
|
||||
|
||||
ggml_tensor* ggml_graph_leaf(const ggml_cgraph* graph, int index) {
|
||||
ggml_tensor* sd_ggml_graph_leaf(const ggml_cgraph* graph, int index) {
|
||||
if (index < 0) {
|
||||
index += graph->n_leafs;
|
||||
}
|
||||
@@ -22,12 +20,12 @@ ggml_tensor* ggml_graph_leaf(const ggml_cgraph* graph, int index) {
|
||||
return graph->leafs[index];
|
||||
}
|
||||
|
||||
void ggml_graph_add_leaf(ggml_cgraph* graph, ggml_tensor* tensor) {
|
||||
void sd_ggml_graph_add_leaf(ggml_cgraph* graph, ggml_tensor* tensor) {
|
||||
GGML_ASSERT(tensor && graph->n_leafs < graph->size);
|
||||
graph->leafs[graph->n_leafs++] = tensor;
|
||||
}
|
||||
|
||||
int32_t ggml_graph_use_count(const ggml_cgraph* graph, const ggml_tensor* tensor) {
|
||||
int32_t sd_ggml_graph_use_count(const ggml_cgraph* graph, const ggml_tensor* tensor) {
|
||||
if (!graph || !tensor || !graph->visited_hash_set.size) {
|
||||
return 0;
|
||||
}
|
||||
@@ -37,7 +35,7 @@ int32_t ggml_graph_use_count(const ggml_cgraph* graph, const ggml_tensor* tensor
|
||||
: 0;
|
||||
}
|
||||
|
||||
bool ggml_graph_cpy_mapped(const ggml_cgraph* src, ggml_cgraph* dst, ggml_graph_tensor_map_fn map, void* user_data) {
|
||||
bool sd_ggml_graph_cpy_mapped(const ggml_cgraph* src, ggml_cgraph* dst, sd_ggml_graph_tensor_map_fn map, void* user_data) {
|
||||
if (!src || !dst || src == dst || !map || dst->grads || dst->grad_accs ||
|
||||
src->n_nodes > dst->size || src->n_leafs > dst->size) {
|
||||
return false;
|
||||
@@ -104,7 +102,7 @@ bool ggml_graph_cpy_mapped(const ggml_cgraph* src, ggml_cgraph* dst, ggml_graph_
|
||||
ggml_graph_add_node(dst, tensor);
|
||||
}
|
||||
for (auto* tensor : leafs) {
|
||||
ggml_graph_add_leaf(dst, tensor);
|
||||
sd_ggml_graph_add_leaf(dst, tensor);
|
||||
}
|
||||
for (const auto& entry : counts) {
|
||||
const size_t index = ggml_hash_insert(&dst->visited_hash_set, entry.first);
|
||||
@@ -113,7 +111,7 @@ bool ggml_graph_cpy_mapped(const ggml_cgraph* src, ggml_cgraph* dst, ggml_graph_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ggml_graph_cpy_use_counts(const ggml_cgraph* src, ggml_cgraph* dst) {
|
||||
bool sd_ggml_graph_cpy_use_counts(const ggml_cgraph* src, ggml_cgraph* dst) {
|
||||
if (!src || !dst || !src->visited_hash_set.size || !dst->visited_hash_set.size) {
|
||||
return false;
|
||||
}
|
||||
@@ -152,7 +150,7 @@ bool ggml_graph_cpy_use_counts(const ggml_cgraph* src, ggml_cgraph* dst) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ggml_status ggml_backend_graph_compute_async_range(ggml_backend_t backend, ggml_cgraph* graph, int first, int last) {
|
||||
ggml_status sd_ggml_backend_graph_compute_async_range(ggml_backend_t backend, ggml_cgraph* graph, int first, int last) {
|
||||
if (!backend || !graph || first < 0 || last < first || last > graph->n_nodes) {
|
||||
return GGML_STATUS_FAILED;
|
||||
}
|
||||
@@ -162,8 +160,6 @@ ggml_status ggml_backend_graph_compute_async_range(ggml_backend_t backend, ggml_
|
||||
auto view = ggml_graph_view(graph, first, last);
|
||||
return ggml_backend_graph_compute_async(backend, &view);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SD_USE_UPSTREAM_GGML
|
||||
#include "ggml-backend-impl.h"
|
||||
#endif
|
||||
|
||||
+8
-17
@@ -3,19 +3,14 @@
|
||||
|
||||
#include "ggml-backend.h"
|
||||
|
||||
#if __has_include("ggml-graph.h")
|
||||
#include "ggml-graph.h"
|
||||
#elif defined(SD_USE_UPSTREAM_GGML)
|
||||
#define SD_GGML_GRAPH_COMPAT
|
||||
|
||||
int ggml_graph_n_leafs(const struct ggml_cgraph* graph);
|
||||
struct ggml_tensor* ggml_graph_leaf(const struct ggml_cgraph* graph, int index);
|
||||
int sd_ggml_graph_n_leafs(const struct ggml_cgraph* graph);
|
||||
struct ggml_tensor* sd_ggml_graph_leaf(const struct ggml_cgraph* graph, int index);
|
||||
// Like ggml_graph_add_node, appends metadata without traversing tensor dependencies.
|
||||
void ggml_graph_add_leaf(struct ggml_cgraph* graph, struct ggml_tensor* tensor);
|
||||
void sd_ggml_graph_add_leaf(struct ggml_cgraph* graph, struct ggml_tensor* tensor);
|
||||
// Returns zero when the tensor has no recorded use count. Includes uses outside graph views.
|
||||
int32_t ggml_graph_use_count(const struct ggml_cgraph* graph, const struct ggml_tensor* tensor);
|
||||
int32_t sd_ggml_graph_use_count(const struct ggml_cgraph* graph, const struct ggml_tensor* tensor);
|
||||
|
||||
typedef struct ggml_tensor* (*ggml_graph_tensor_map_fn)(const struct ggml_tensor* tensor, void* user_data);
|
||||
typedef struct ggml_tensor* (*sd_ggml_graph_tensor_map_fn)(const struct ggml_tensor* tensor, void* user_data);
|
||||
|
||||
// Copies forward node/leaf order and recorded use counts, including external consumers.
|
||||
// The callback must be injective and may return NULL for dependencies outside the
|
||||
@@ -23,21 +18,17 @@ typedef struct ggml_tensor* (*ggml_graph_tensor_map_fn)(const struct ggml_tensor
|
||||
// Tensor storage and edges are mapped by the caller.
|
||||
// The destination must have no gradients and enough capacity. Gradients are not copied.
|
||||
// Invalid mappings leave the destination unchanged. src and dst must be distinct.
|
||||
bool ggml_graph_cpy_mapped(const struct ggml_cgraph* src, struct ggml_cgraph* dst, ggml_graph_tensor_map_fn map, void* user_data);
|
||||
bool sd_ggml_graph_cpy_mapped(const struct ggml_cgraph* src, struct ggml_cgraph* dst, sd_ggml_graph_tensor_map_fn map, void* user_data);
|
||||
|
||||
// Copies recorded counts for tensors in dst's node/leaf lists. Other metadata is unchanged.
|
||||
// This preserves external consumers when constructing an inference graph segment.
|
||||
bool ggml_graph_cpy_use_counts(const struct ggml_cgraph* src, struct ggml_cgraph* dst);
|
||||
bool sd_ggml_graph_cpy_use_counts(const struct ggml_cgraph* src, struct ggml_cgraph* dst);
|
||||
|
||||
// Executes nodes [first, last) with the original graph's use counts. No graph ownership
|
||||
// is transferred. Tensor storage must already be allocated; invalid bounds fail.
|
||||
enum ggml_status ggml_backend_graph_compute_async_range(ggml_backend_t backend,
|
||||
enum ggml_status sd_ggml_backend_graph_compute_async_range(ggml_backend_t backend,
|
||||
struct ggml_cgraph* graph,
|
||||
int first,
|
||||
int last);
|
||||
|
||||
#else
|
||||
#error "Patched ggml requires ggml-graph.h; select SD_USE_UPSTREAM_GGML for upstream compatibility"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -647,7 +647,7 @@ ggml_status sd_backend_graph_compute_with_eval_callback(ggml_backend_t backend,
|
||||
need = callback_eval(t, true, callback_eval_user_data);
|
||||
}
|
||||
|
||||
status = ggml_backend_graph_compute_async_range(backend, gf, j0, j1 + 1);
|
||||
status = sd_ggml_backend_graph_compute_async_range(backend, gf, j0, j1 + 1);
|
||||
if (status != GGML_STATUS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
+20
-20
@@ -35,8 +35,8 @@ namespace sd::ggml_graph_cut {
|
||||
static int graph_leaf_index(ggml_cgraph* gf, const ggml_tensor* tensor) {
|
||||
GGML_ASSERT(gf != nullptr);
|
||||
GGML_ASSERT(tensor != nullptr);
|
||||
for (int i = 0; i < ggml_graph_n_leafs(gf); ++i) {
|
||||
if (ggml_graph_leaf(gf, i) == tensor) {
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(gf); ++i) {
|
||||
if (sd_ggml_graph_leaf(gf, i) == tensor) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -389,7 +389,7 @@ namespace sd::ggml_graph_cut {
|
||||
return fail(segment_label + " references an unavailable cut node " +
|
||||
std::to_string(input.node_index));
|
||||
}
|
||||
} else if (input.leaf_index < 0 || input.leaf_index >= ggml_graph_n_leafs(gf)) {
|
||||
} else if (input.leaf_index < 0 || input.leaf_index >= sd_ggml_graph_n_leafs(gf)) {
|
||||
return fail(segment_label + " references an invalid leaf " +
|
||||
std::to_string(input.leaf_index));
|
||||
}
|
||||
@@ -444,15 +444,15 @@ namespace sd::ggml_graph_cut {
|
||||
|
||||
int leaf_count(ggml_cgraph* gf) {
|
||||
GGML_ASSERT(gf != nullptr);
|
||||
return ggml_graph_n_leafs(gf);
|
||||
return sd_ggml_graph_n_leafs(gf);
|
||||
}
|
||||
|
||||
ggml_tensor* leaf_tensor(ggml_cgraph* gf, int leaf_index) {
|
||||
GGML_ASSERT(gf != nullptr);
|
||||
if (leaf_index < 0 || leaf_index >= ggml_graph_n_leafs(gf)) {
|
||||
if (leaf_index < 0 || leaf_index >= sd_ggml_graph_n_leafs(gf)) {
|
||||
return nullptr;
|
||||
}
|
||||
return ggml_graph_leaf(gf, leaf_index);
|
||||
return sd_ggml_graph_leaf(gf, leaf_index);
|
||||
}
|
||||
|
||||
ggml_backend_buffer_t tensor_buffer(const ggml_tensor* tensor) {
|
||||
@@ -548,11 +548,11 @@ namespace sd::ggml_graph_cut {
|
||||
};
|
||||
|
||||
std::vector<uint64_t> graph_layout(ggml_cgraph* graph, bool include_bindings) {
|
||||
const size_t graph_size = static_cast<size_t>(ggml_graph_n_leafs(graph)) + ggml_graph_n_nodes(graph);
|
||||
const size_t graph_size = static_cast<size_t>(sd_ggml_graph_n_leafs(graph)) + ggml_graph_n_nodes(graph);
|
||||
GraphLayoutTensors layout_tensors(graph_size);
|
||||
const auto& tensors = layout_tensors.tensors;
|
||||
for (int i = 0; i < ggml_graph_n_leafs(graph); ++i) {
|
||||
layout_tensors.add(ggml_graph_leaf(graph, i));
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(graph); ++i) {
|
||||
layout_tensors.add(sd_ggml_graph_leaf(graph, i));
|
||||
}
|
||||
for (int i = 0; i < ggml_graph_n_nodes(graph); ++i) {
|
||||
layout_tensors.add(ggml_graph_node(graph, i));
|
||||
@@ -568,9 +568,9 @@ namespace sd::ggml_graph_cut {
|
||||
GGML_MAX_OP_PARAMS / sizeof(int32_t) + (include_bindings ? 2 : 0);
|
||||
signature.reserve(2 + graph_size + tensors.size() * tensor_fields);
|
||||
signature.push_back(ggml_graph_n_nodes(graph));
|
||||
signature.push_back(ggml_graph_n_leafs(graph));
|
||||
for (int i = 0; i < ggml_graph_n_leafs(graph); ++i) {
|
||||
signature.push_back(layout_tensors.index(ggml_graph_leaf(graph, i)));
|
||||
signature.push_back(sd_ggml_graph_n_leafs(graph));
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(graph); ++i) {
|
||||
signature.push_back(layout_tensors.index(sd_ggml_graph_leaf(graph, i)));
|
||||
}
|
||||
for (int i = 0; i < ggml_graph_n_nodes(graph); ++i) {
|
||||
signature.push_back(layout_tensors.index(ggml_graph_node(graph, i)));
|
||||
@@ -606,12 +606,12 @@ namespace sd::ggml_graph_cut {
|
||||
const Plan& plan,
|
||||
const std::vector<uint64_t>& layout) {
|
||||
GGML_ASSERT(gf != nullptr);
|
||||
if (plan.leaf_names.size() != static_cast<size_t>(ggml_graph_n_leafs(gf)) ||
|
||||
if (plan.leaf_names.size() != static_cast<size_t>(sd_ggml_graph_n_leafs(gf)) ||
|
||||
plan.layout != layout) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ggml_graph_n_leafs(gf); ++i) {
|
||||
if (plan.leaf_names[i] != ggml_graph_leaf(gf, i)->name) {
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(gf); ++i) {
|
||||
if (plan.leaf_names[i] != sd_ggml_graph_leaf(gf, i)->name) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -654,7 +654,7 @@ namespace sd::ggml_graph_cut {
|
||||
}
|
||||
return ggml_graph_node(gf, input_ref.node_index);
|
||||
}
|
||||
if (input_ref.leaf_index < 0 || input_ref.leaf_index >= ggml_graph_n_leafs(gf)) {
|
||||
if (input_ref.leaf_index < 0 || input_ref.leaf_index >= sd_ggml_graph_n_leafs(gf)) {
|
||||
return nullptr;
|
||||
}
|
||||
return leaf_tensor(gf, input_ref.leaf_index);
|
||||
@@ -735,7 +735,7 @@ namespace sd::ggml_graph_cut {
|
||||
GGML_ASSERT(segment_graph != nullptr);
|
||||
|
||||
for (ggml_tensor* leaf : leaves) {
|
||||
ggml_graph_add_leaf(segment_graph, leaf);
|
||||
sd_ggml_graph_add_leaf(segment_graph, leaf);
|
||||
}
|
||||
|
||||
for (int output_node_index : segment.output_node_indices) {
|
||||
@@ -752,7 +752,7 @@ namespace sd::ggml_graph_cut {
|
||||
for (int node_idx : segment.internal_node_indices) {
|
||||
ggml_graph_add_node(segment_graph, ggml_graph_node(gf, node_idx));
|
||||
}
|
||||
GGML_ASSERT(ggml_graph_cpy_use_counts(gf, segment_graph));
|
||||
GGML_ASSERT(sd_ggml_graph_cpy_use_counts(gf, segment_graph));
|
||||
*graph_ctx_out = graph_ctx;
|
||||
return segment_graph;
|
||||
}
|
||||
@@ -888,8 +888,8 @@ namespace sd::ggml_graph_cut {
|
||||
return plan;
|
||||
}
|
||||
plan.layout = graph_layout(gf, false);
|
||||
for (int i = 0; i < ggml_graph_n_leafs(gf); ++i) {
|
||||
plan.leaf_names.emplace_back(ggml_graph_leaf(gf, i)->name);
|
||||
for (int i = 0; i < sd_ggml_graph_n_leafs(gf); ++i) {
|
||||
plan.leaf_names.emplace_back(sd_ggml_graph_leaf(gf, i)->name);
|
||||
}
|
||||
plan.compute_buffer_size =
|
||||
measure_graph_compute_buffer(backend, gf, params_tensor_set);
|
||||
|
||||
Reference in new issue
Block a user