@@ -5091,6 +5091,89 @@ static void ggml_backend_cuda_graph_optimize(ggml_backend_t backend, ggml_cgraph
50915091 }
50925092}
50935093
5094+ struct ggml_cuda_graph_plan {
5095+ cudaGraph_t graph = nullptr ;
5096+ cudaGraphExec_t instance = nullptr ;
5097+ };
5098+
5099+ static ggml_backend_graph_plan_t ggml_backend_cuda_graph_plan_create (ggml_backend_t backend, const struct ggml_cgraph * cgraph) {
5100+ ggml_backend_cuda_context * cuda_ctx = (ggml_backend_cuda_context *)backend->context ;
5101+ ggml_cuda_set_device (cuda_ctx->device );
5102+
5103+ auto * plan = new ggml_cuda_graph_plan ();
5104+
5105+ {
5106+ std::lock_guard<std::mutex> lock (ggml_cuda_lock);
5107+ ggml_cuda_lock_counter.fetch_add (1 , std::memory_order_relaxed);
5108+ }
5109+
5110+ CUDA_CHECK (cudaStreamBeginCapture (cuda_ctx->stream (), cudaStreamCaptureModeRelaxed));
5111+
5112+ ggml_cuda_graph_evaluate_and_capture (cuda_ctx, const_cast <ggml_cgraph *>(cgraph), false , false , nullptr );
5113+
5114+ CUDA_CHECK (cudaStreamEndCapture (cuda_ctx->stream (), &plan->graph ));
5115+ CUDA_CHECK (cudaGraphInstantiate (&plan->instance , plan->graph , nullptr , nullptr , 0 ));
5116+
5117+ return (ggml_backend_graph_plan_t )plan;
5118+ }
5119+
5120+ static void ggml_backend_cuda_graph_plan_free (ggml_backend_t backend, ggml_backend_graph_plan_t plan) {
5121+ (void )backend;
5122+ auto * p = (ggml_cuda_graph_plan *)plan;
5123+ if (!p) return ;
5124+ if (p->instance ) { CUDA_CHECK (cudaGraphExecDestroy (p->instance )); p->instance = nullptr ; }
5125+ if (p->graph ) { CUDA_CHECK (cudaGraphDestroy (p->graph )); p->graph = nullptr ; }
5126+ delete p;
5127+ }
5128+
5129+ static enum ggml_status ggml_backend_cuda_graph_plan_compute (ggml_backend_t backend, ggml_backend_graph_plan_t plan) {
5130+ ggml_backend_cuda_context * cuda_ctx = (ggml_backend_cuda_context *)backend->context ;
5131+ ggml_cuda_set_device (cuda_ctx->device );
5132+ auto * p = (ggml_cuda_graph_plan *)plan;
5133+ CUDA_CHECK (cudaGraphLaunch (p->instance , cuda_ctx->stream ()));
5134+ return GGML_STATUS_SUCCESS ;
5135+ }
5136+
5137+ static void ggml_backend_cuda_graph_plan_update (ggml_backend_t backend, ggml_backend_graph_plan_t plan, const struct ggml_cgraph * cgraph) {
5138+ ggml_backend_cuda_context * cuda_ctx = (ggml_backend_cuda_context *)backend->context ;
5139+ ggml_cuda_set_device (cuda_ctx->device );
5140+ auto * p = (ggml_cuda_graph_plan *)plan;
5141+ if (!p || !p->instance ) return ;
5142+
5143+ cudaGraph_t new_graph = nullptr ;
5144+
5145+ {
5146+ std::lock_guard<std::mutex> lock (ggml_cuda_lock);
5147+ ggml_cuda_lock_counter.fetch_add (1 , std::memory_order_relaxed);
5148+ }
5149+
5150+ CUDA_CHECK (cudaStreamBeginCapture (cuda_ctx->stream (), cudaStreamCaptureModeRelaxed));
5151+
5152+ ggml_cuda_graph_evaluate_and_capture (cuda_ctx, const_cast <ggml_cgraph *>(cgraph), false , false , nullptr );
5153+
5154+ CUDA_CHECK (cudaStreamEndCapture (cuda_ctx->stream (), &new_graph));
5155+
5156+ #if CUDART_VERSION >= 12000
5157+ cudaGraphExecUpdateResultInfo result_info;
5158+ cudaError_t stat = cudaGraphExecUpdate (p->instance , new_graph, &result_info);
5159+ #else
5160+ cudaGraphNode_t errorNode;
5161+ cudaGraphExecUpdateResult result_info;
5162+ cudaError_t stat = cudaGraphExecUpdate (p->instance , new_graph, &errorNode, &result_info);
5163+ #endif
5164+
5165+ if (stat == cudaErrorGraphExecUpdateFailure) {
5166+ (void )cudaGetLastError ();
5167+ CUDA_CHECK (cudaGraphExecDestroy (p->instance ));
5168+ p->instance = nullptr ;
5169+ CUDA_CHECK (cudaGraphInstantiate (&p->instance , new_graph, nullptr , nullptr , 0 ));
5170+ } else {
5171+ GGML_ASSERT (stat == cudaSuccess);
5172+ }
5173+
5174+ CUDA_CHECK (cudaGraphDestroy (new_graph));
5175+ }
5176+
50945177static const ggml_backend_i ggml_backend_cuda_interface = {
50955178 /* .get_name = */ ggml_backend_cuda_get_name,
50965179 /* .free = */ ggml_backend_cuda_free,
@@ -5100,10 +5183,10 @@ static const ggml_backend_i ggml_backend_cuda_interface = {
51005183 /* .get_tensor_2d_async = */ ggml_backend_cuda_get_tensor_2d_async,
51015184 /* .cpy_tensor_async = */ ggml_backend_cuda_cpy_tensor_async,
51025185 /* .synchronize = */ ggml_backend_cuda_synchronize,
5103- /* .graph_plan_create = */ NULL ,
5104- /* .graph_plan_free = */ NULL ,
5105- /* .graph_plan_update = */ NULL ,
5106- /* .graph_plan_compute = */ NULL ,
5186+ /* .graph_plan_create = */ ggml_backend_cuda_graph_plan_create ,
5187+ /* .graph_plan_free = */ ggml_backend_cuda_graph_plan_free ,
5188+ /* .graph_plan_update = */ ggml_backend_cuda_graph_plan_update ,
5189+ /* .graph_plan_compute = */ ggml_backend_cuda_graph_plan_compute ,
51075190 /* .graph_compute = */ ggml_backend_cuda_graph_compute,
51085191 /* .event_record = */ ggml_backend_cuda_event_record,
51095192 /* .event_wait = */ ggml_backend_cuda_event_wait,
0 commit comments