Commit 3bce8bd50 for llama.cpp
commit 3bce8bd50c8f1c6bb0c784e3a87f640882091077
Author: Aman Gupta <amangupta052@gmail.com>
Date: Thu Nov 12 17:24:40 2026 +0800
ggml-backend : prefetch only inputs computed by earlier splits (#32100)
* ggml-backend : prefetch only inputs computed by earlier splits
The copy callback of a split runs after the prefetch and can write tensors that a later split reads, e.g. the MoE cache uploads missed experts into its bank. A prefetch of such a tensor reads it before the write.
* llama : skip the MoE cache when its device cannot run the cached mul_mat_id
Otherwise the scheduler runs the matmul on another backend and copies the whole bank every ubatch.
diff --git a/ggml/src/ggml-backend.cpp b/ggml/src/ggml-backend.cpp
index 961990f85..b70d0d874 100644
--- a/ggml/src/ggml-backend.cpp
+++ b/ggml/src/ggml-backend.cpp
@@ -2172,8 +2172,13 @@ static void ggml_backend_sched_prefetch_inputs(ggml_backend_sched_t sched, int s
continue;
}
- // not if this split computes or writes the input
+ // only results of earlier splits, the copy callback of this split runs later and can write other tensors (e.g. the MoE cache)
const struct ggml_tensor * base = input->view_src ? input->view_src : input;
+ if (base->buffer == NULL || ggml_backend_buffer_get_usage(base->buffer) != GGML_BACKEND_BUFFER_USAGE_COMPUTE) {
+ continue;
+ }
+
+ // not if this split computes or writes the input
bool written = false;
for (int j = 0; j < split->graph.n_nodes && !written; j++) {
const struct ggml_tensor * node = split->graph.nodes[j];
diff --git a/src/llama-graph.cpp b/src/llama-graph.cpp
index cc7779164..50a76f691 100644
--- a/src/llama-graph.cpp
+++ b/src/llama-graph.cpp
@@ -2687,7 +2687,16 @@ llm_graph_moe_cache_slots llm_graph_context::build_moe_cache_slots(
return { nullptr, nullptr };
}
for (ggml_tensor * w : { up_exps, gate_exps, down_exps, gate_up_exps }) {
- if (w != nullptr && moe_cache->get_experts(w) == nullptr) {
+ if (w == nullptr) {
+ continue;
+ }
+ ggml_tensor * experts = moe_cache->get_experts(w);
+ if (experts == nullptr) {
+ return { nullptr, nullptr };
+ }
+ // the device of the cache must compute the matmul, else the scheduler copies the cache to another backend
+ ggml_tensor * b = ggml_new_tensor_3d(ctx0, GGML_TYPE_F32, experts->ne[0], w == down_exps ? selected_experts->ne[0] : 1, selected_experts->ne[1]);
+ if (!ggml_backend_supports_op(moe_cache->backend(il), ggml_mul_mat_id(ctx0, experts, b, selected_experts))) {
return { nullptr, nullptr };
}
}