Skip to content

Commit c9df355

Browse files
committed
WIP
1 parent 21ca261 commit c9df355

1 file changed

Lines changed: 40 additions & 13 deletions

File tree

ggml/src/ggml-cuda/ggml-cuda.cu

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4779,11 +4779,6 @@ static void ggml_backend_cuda_graph_optimize(ggml_backend_t backend, ggml_cgraph
47794779
// store {fork_idx, join_idx}
47804780
std::vector<std::pair<int, int>> concurrent_node_ranges;
47814781

4782-
// per-event lists of concurrent branch nodes to place in the dedicated scratch buffer (below),
4783-
// so the branches are mutually disjoint and disjoint from tensors read across the region -
4784-
// this replaces the fragile node interleaving that ggml-alloc/execution order can desync
4785-
std::vector<std::vector<const ggml_tensor *>> concurrent_groups;
4786-
47874782
for (const auto & [root_node, count] : fan_out) {
47884783
if (count >= min_fan_out && count <= max_fan_out) {
47894784
const int root_node_idx = node_indices[root_node];
@@ -4875,6 +4870,10 @@ static void ggml_backend_cuda_graph_optimize(ggml_backend_t backend, ggml_cgraph
48754870
int fork_node_idx = node_indices[root_node];
48764871
int join_node_idx = node_indices[join_node];
48774872

4873+
int current_branch_idx = 0;
4874+
int current_node_idx = fork_node_idx + 1;
4875+
const int n_branches = nodes_per_branch.size();
4876+
48784877
int total_branch_nodes = 0;
48794878
for (std::vector<const ggml_tensor *> branch_nodes : nodes_per_branch) {
48804879
total_branch_nodes += branch_nodes.size();
@@ -4903,20 +4902,48 @@ static void ggml_backend_cuda_graph_optimize(ggml_backend_t backend, ggml_cgraph
49034902
GGML_LOG_DEBUG("Adding stream at node %s %p\n", root_node->name, root_node);
49044903
concurrent_node_ranges.emplace_back(fork_node_idx, join_node_idx);
49054904

4906-
// place all branch nodes in the dedicated scratch buffer (below) instead of
4907-
// interleaving them: ggml-alloc then keeps the branches mutually disjoint and
4908-
// disjoint from the fork output that every branch reads concurrently
4909-
std::vector<const ggml_tensor *> group;
4910-
for (const auto & branch_nodes : nodes_per_branch) {
4911-
for (const ggml_tensor * n : branch_nodes) {
4912-
group.push_back(n);
4905+
// interleave tensors to extend lifetimes so that ggml graph doesn't recycle them
4906+
// example transformation:
4907+
// [attn-norm, QMul, QNorm, QRope, KMul, KNorm, KRope, VMul, attn] ->
4908+
// [attn-norm, QMul, KMul, VMul, QNorm, VNorm, QRope, KRope, attn]
4909+
while (current_node_idx < join_node_idx) {
4910+
std::vector<const ggml_tensor *> & branch_nodes = nodes_per_branch[current_branch_idx];
4911+
4912+
bool has_node = false;
4913+
for (std::vector<const ggml_tensor *> branch_node : nodes_per_branch) {
4914+
has_node |= branch_node.size() > 0;
4915+
}
4916+
4917+
GGML_ASSERT(has_node);
4918+
4919+
if (branch_nodes.empty()) {
4920+
current_branch_idx = (current_branch_idx + 1) % n_branches;
4921+
continue;
4922+
}
4923+
4924+
cgraph->nodes[current_node_idx] = const_cast<ggml_tensor *>(branch_nodes.front());
4925+
current_node_idx++;
4926+
branch_nodes.erase(branch_nodes.begin());
4927+
4928+
// append all empty nodes
4929+
while (!branch_nodes.empty() && is_noop(branch_nodes.front())) {
4930+
cgraph->nodes[current_node_idx] = const_cast<ggml_tensor *>(branch_nodes.front());
4931+
current_node_idx++;
4932+
branch_nodes.erase(branch_nodes.begin());
49134933
}
4934+
4935+
current_branch_idx = (current_branch_idx + 1) % n_branches;
49144936
}
4915-
concurrent_groups.push_back(std::move(group));
49164937
}
49174938
}
49184939
}
49194940

4941+
// per-event lists of concurrent branch nodes to place in the dedicated scratch buffer (below),
4942+
// so the branches are mutually disjoint and disjoint from tensors read across the region.
4943+
// The QKV path below uses the legacy node interleaving instead; only the MoE shared-expert path
4944+
// populates this, so the two disjointness mechanisms coexist.
4945+
std::vector<std::vector<const ggml_tensor *>> concurrent_groups;
4946+
49204947
ggml_cuda_detect_shared_expert_concurrency(cgraph, cuda_ctx, node_indices, concurrent_node_ranges, concurrent_groups);
49214948

49224949
// Place every concurrent branch (attention QKV and MoE shared-expert) in a dedicated buffer so

0 commit comments

Comments
 (0)