diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh index 3111d1f8f302..aa3c05c4022d 100644 --- a/ggml/src/ggml-cuda/common.cuh +++ b/ggml/src/ggml-cuda/common.cuh @@ -1459,11 +1459,12 @@ struct ggml_backend_cuda_context { // Map from graph key to cuda_graph - allows multiple graphs per context when the // computation is split across CPU/GPU (e.g., with --n-cpu-moe), and when the same // split is called with different tensor shapes (e.g. a speculative verify batch) - std::unordered_map> cuda_graphs; - // a cuda graph instance is only valid for the shapes it captured, so a caller that - // alternates shapes needs one instance per shape to stay on the graph path - static const size_t max_cuda_graphs = 64; + // alternates shapes needs one instance per shape to stay on the graph path. the map is + // bounded only by the time based sweep below, as upstream does: tensor split mode alone + // needs about 2 * n_layers + 1 graphs per device and shape, so any count cap small enough + // to matter evicts graphs that are still in use and re-captures them on every token + std::unordered_map> cuda_graphs; int64_t last_graph_eviction_sweep = 0; @@ -1484,16 +1485,6 @@ struct ggml_backend_cuda_context { auto it = cuda_graphs.find(graph_key); if (it == cuda_graphs.end()) { - // a workload with many distinct shapes must not grow this without bound - while (cuda_graphs.size() >= max_cuda_graphs) { - auto lru = cuda_graphs.begin(); - for (auto c = cuda_graphs.begin(); c != cuda_graphs.end(); ++c) { - if (c->second->last_used_time < lru->second->last_used_time) { - lru = c; - } - } - cuda_graphs.erase(lru); - } it = cuda_graphs.emplace(graph_key, std::make_unique()).first; } it->second->last_used_time = time_now;