Commit c56be864f for llama.cpp
commit c56be864f482dc88a6d62a0816a265034941935f
Author: Aman Gupta <amangupta052@gmail.com>
Date: Sat Nov 14 22:14:48 2026 +0800
ggml-backend : start a new split at an incompatible weight in a split without inputs (#31775)
diff --git a/ggml/src/ggml-backend.cpp b/ggml/src/ggml-backend.cpp
index b70d0d874..2e2f9c036 100644
--- a/ggml/src/ggml-backend.cpp
+++ b/ggml/src/ggml-backend.cpp
@@ -1727,6 +1727,7 @@ void ggml_backend_sched_split_graph(ggml_backend_sched_t sched, struct ggml_cgra
split->i_start = 0;
split->n_inputs = 0;
int cur_backend_id = split->backend_id;
+ bool split_has_nodes = false;
for (; i < graph->n_nodes; i++) {
struct ggml_tensor * node = graph->nodes[i];
@@ -1739,8 +1740,9 @@ void ggml_backend_sched_split_graph(ggml_backend_sched_t sched, struct ggml_cgra
GGML_ASSERT(node_backend_id != -1); // all nodes should be assigned by now, this can happen if there is no CPU fallback
// check if we should start a new split based on the sources of the current node
+ // this also applies to a split without inputs, e.g. one that follows a split that only writes to a host buffer
bool need_new_split = false;
- if (node_backend_id == cur_backend_id && split->n_inputs > 0) {
+ if (node_backend_id == cur_backend_id && split_has_nodes) {
for (int j = 0; j < GGML_MAX_SRC; j++) {
struct ggml_tensor * src = node->src[j];
if (src == NULL) {
@@ -1777,6 +1779,7 @@ void ggml_backend_sched_split_graph(ggml_backend_sched_t sched, struct ggml_cgra
split->n_inputs = 0;
cur_backend_id = node_backend_id;
}
+ split_has_nodes = true;
// find inputs that are not on the same backend
for (int j = 0; j < GGML_MAX_SRC; j++) {
diff --git a/src/llama-moe-cache.cpp b/src/llama-moe-cache.cpp
index 1070b92b8..ba35af021 100644
--- a/src/llama-moe-cache.cpp
+++ b/src/llama-moe-cache.cpp
@@ -788,7 +788,7 @@ struct llama_moe_cache::impl {
GGML_ASSERT(lookup != nullptr);
// the selected experts must be computed in an earlier split
- // the scheduler starts a new split at the lookup because it reads a host weight, but only if the split already has inputs
+ // the scheduler starts a new split at the lookup because it reads a host weight, unless the lookup is the first node of its split
const ggml_tensor * sel = lookup->src[1];
for (int i = 0; i < n_nodes; ++i) {
const ggml_tensor * node = ggml_graph_node(graph, i);