@@ -2969,56 +2969,64 @@ static bool ggml_cuda_graph_node_properties_match(ggml_tensor * node, ggml_cuda_
29692969 return true ;
29702970}
29712971
2972+ static const void * ggml_cuda_graph_get_key (ggml_cgraph * cgraph) {
2973+ return cgraph->nodes [0 ];
2974+ }
2975+
29722976static bool ggml_cuda_graph_update_required (ggml_backend_cuda_context * cuda_ctx, ggml_cgraph * cgraph) {
29732977
29742978 bool res = false ;
29752979
2976- if (cuda_ctx->cuda_graph ->instance == nullptr ) {
2980+ const void * graph_key = ggml_cuda_graph_get_key (cgraph);
2981+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
2982+
2983+ if (graph->instance == nullptr ) {
29772984 res = true ;
29782985 }
29792986
29802987 // Check if the graph size has changed
2981- if (cuda_ctx-> cuda_graph ->props .size () != (size_t )cgraph->n_nodes + cgraph->n_leafs ) {
2988+ if (graph ->props .size () != (size_t )cgraph->n_nodes + cgraph->n_leafs ) {
29822989 res = true ;
2983- cuda_ctx-> cuda_graph ->props .resize (cgraph->n_nodes + cgraph->n_leafs );
2990+ graph ->props .resize (cgraph->n_nodes + cgraph->n_leafs );
29842991 }
29852992
29862993 // Loop over nodes in GGML graph to determine if CUDA graph update is required
29872994 // and store properties to allow this comparison for the next token
29882995 for (int i = 0 ; i < cgraph->n_nodes ; i++) {
29892996 bool props_match = true ;
29902997 if (!res) {
2991- props_match = ggml_cuda_graph_node_properties_match (cgraph->nodes [i], &cuda_ctx-> cuda_graph ->props [i]);
2998+ props_match = ggml_cuda_graph_node_properties_match (cgraph->nodes [i], &graph ->props [i]);
29922999 }
29933000 if (!props_match) {
29943001 res = true ;
29953002 }
2996- ggml_cuda_graph_node_set_properties (&cuda_ctx-> cuda_graph ->props [i], cgraph->nodes [i]);
3003+ ggml_cuda_graph_node_set_properties (&graph ->props [i], cgraph->nodes [i]);
29973004 }
29983005
29993006 for (int i = 0 ; i < cgraph->n_leafs ; i++) {
3000- bool props_match= true ;
3007+ bool props_match = true ;
30013008 if (!res) {
3002- props_match = ggml_cuda_graph_node_properties_match (cgraph->leafs [i], &cuda_ctx-> cuda_graph ->props [cgraph->n_nodes + i]);
3009+ props_match = ggml_cuda_graph_node_properties_match (cgraph->leafs [i], &graph ->props [cgraph->n_nodes + i]);
30033010 }
30043011 if (!props_match) {
30053012 res = true ;
30063013 }
3007- ggml_cuda_graph_node_set_properties (&cuda_ctx-> cuda_graph ->props [cgraph->n_nodes + i], cgraph->leafs [i]);
3014+ ggml_cuda_graph_node_set_properties (&graph ->props [cgraph->n_nodes + i], cgraph->leafs [i]);
30083015 }
30093016
30103017 return res;
30113018}
30123019
3013- static void ggml_cuda_graph_update_executable (ggml_backend_cuda_context * cuda_ctx) {
3020+ static void ggml_cuda_graph_update_executable (ggml_backend_cuda_context * cuda_ctx, const void * graph_key) {
3021+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
30143022
30153023#if CUDART_VERSION >= 12000
30163024 cudaGraphExecUpdateResultInfo result_info;
3017- cudaError_t stat = cudaGraphExecUpdate (cuda_ctx-> cuda_graph -> instance , cuda_ctx-> cuda_graph ->graph , &result_info);
3025+ cudaError_t stat = cudaGraphExecUpdate (graph-> instance , graph ->graph , &result_info);
30183026#else
30193027 cudaGraphNode_t errorNode;
30203028 cudaGraphExecUpdateResult result_info;
3021- cudaError_t stat = cudaGraphExecUpdate (cuda_ctx-> cuda_graph -> instance , cuda_ctx-> cuda_graph ->graph , &errorNode, &result_info);
3029+ cudaError_t stat = cudaGraphExecUpdate (graph-> instance , graph ->graph , &errorNode, &result_info);
30223030#endif // CUDART_VERSION >= 12000
30233031
30243032 if (stat == cudaErrorGraphExecUpdateFailure) {
@@ -3029,14 +3037,14 @@ static void ggml_cuda_graph_update_executable(ggml_backend_cuda_context * cuda_c
30293037 // The pre-existing graph exec cannot be updated due to violated constraints
30303038 // so instead clear error and re-instantiate
30313039 (void )cudaGetLastError ();
3032- CUDA_CHECK (cudaGraphExecDestroy (cuda_ctx-> cuda_graph ->instance ));
3033- cuda_ctx-> cuda_graph ->instance = nullptr ;
3034- CUDA_CHECK (cudaGraphInstantiate (&cuda_ctx-> cuda_graph -> instance , cuda_ctx-> cuda_graph ->graph , NULL , NULL , 0 ));
3040+ CUDA_CHECK (cudaGraphExecDestroy (graph ->instance ));
3041+ graph ->instance = nullptr ;
3042+ CUDA_CHECK (cudaGraphInstantiate (&graph-> instance , graph ->graph , NULL , NULL , 0 ));
30353043 } else {
30363044 GGML_ASSERT (stat == cudaSuccess);
30373045 }
30383046}
3039- #endif
3047+ #endif // USE_CUDA_GRAPH
30403048
30413049static bool ggml_cuda_should_fuse_rope_set_rows (const ggml_tensor * rope,
30423050 const ggml_tensor * view,
@@ -3241,7 +3249,7 @@ static bool ggml_cuda_can_fuse(const struct ggml_cgraph * cgraph, int node_idx,
32413249 return false ;
32423250}
32433251
3244- static void ggml_cuda_graph_evaluate_and_capture (ggml_backend_cuda_context * cuda_ctx, ggml_cgraph * cgraph, const bool use_cuda_graph, const bool cuda_graph_update_required) {
3252+ static void ggml_cuda_graph_evaluate_and_capture (ggml_backend_cuda_context * cuda_ctx, ggml_cgraph * cgraph, const bool use_cuda_graph, const bool cuda_graph_update_required, const void * graph_key ) {
32453253 bool graph_evaluated_or_captured = false ;
32463254
32473255 // flag used to determine whether it is an integrated_gpu
@@ -3695,13 +3703,14 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
36953703 }
36963704
36973705#ifdef USE_CUDA_GRAPH
3706+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
36983707 if (use_cuda_graph && cuda_graph_update_required) { // End CUDA graph capture
3699- if (cuda_ctx-> cuda_graph ->graph != nullptr ) {
3700- CUDA_CHECK (cudaGraphDestroy (cuda_ctx-> cuda_graph ->graph ));
3701- cuda_ctx-> cuda_graph ->graph = nullptr ;
3708+ if (graph ->graph != nullptr ) {
3709+ CUDA_CHECK (cudaGraphDestroy (graph ->graph ));
3710+ graph ->graph = nullptr ;
37023711 }
37033712
3704- CUDA_CHECK (cudaStreamEndCapture (cuda_ctx->stream (), &cuda_ctx-> cuda_graph ->graph ));
3713+ CUDA_CHECK (cudaStreamEndCapture (cuda_ctx->stream (), &graph ->graph ));
37053714 graph_evaluated_or_captured = true ; // CUDA graph has been captured
37063715
37073716 std::lock_guard<std::mutex> lock (ggml_cuda_lock);
@@ -3714,40 +3723,39 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
37143723 }
37153724
37163725 if (use_cuda_graph) {
3717- if (cuda_ctx->cuda_graph ->instance == nullptr ) { // Create executable graph from captured graph.
3718- CUDA_CHECK (cudaGraphInstantiate (&cuda_ctx->cuda_graph ->instance , cuda_ctx->cuda_graph ->graph , NULL , NULL , 0 ));
3726+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
3727+ if (graph->instance == nullptr ) { // Create executable graph from captured graph.
3728+ CUDA_CHECK (cudaGraphInstantiate (&graph->instance , graph->graph , NULL , NULL , 0 ));
37193729 }
37203730 if (cuda_graph_update_required) { // Update graph executable
3721- ggml_cuda_graph_update_executable (cuda_ctx);
3731+ ggml_cuda_graph_update_executable (cuda_ctx, graph_key );
37223732 }
37233733 // Launch graph
3724- CUDA_CHECK (cudaGraphLaunch (cuda_ctx-> cuda_graph ->instance , cuda_ctx->stream ()));
3734+ CUDA_CHECK (cudaGraphLaunch (graph ->instance , cuda_ctx->stream ()));
37253735#else
37263736 graph_evaluated_or_captured = true ;
37273737#endif // USE_CUDA_GRAPH
37283738 }
37293739}
37303740
3731- static bool ggml_cuda_graph_set_enabled (ggml_backend_cuda_context * cuda_ctx) {
3741+ static bool ggml_cuda_graph_set_enabled (ggml_backend_cuda_context * cuda_ctx, const void * graph_key ) {
37323742
37333743#ifdef USE_CUDA_GRAPH
3744+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
37343745
3735- if (cuda_ctx->cuda_graph == nullptr ) {
3736- cuda_ctx->cuda_graph .reset (new ggml_cuda_graph ());
3737- }
3738-
3739- if (cuda_ctx->cuda_graph ->graph == nullptr ) {
3746+ if (graph->graph == nullptr ) {
37403747 if (ggml_cuda_info ().devices [cuda_ctx->device ].cc < GGML_CUDA_CC_AMPERE ) {
3741- if (!cuda_ctx-> cuda_graph ->disable_due_to_gpu_arch ) {
3748+ if (!graph ->disable_due_to_gpu_arch ) {
37423749 GGML_LOG_DEBUG (" %s: disabling CUDA graphs due to GPU architecture\n " , __func__);
37433750 }
3744- cuda_ctx-> cuda_graph ->disable_due_to_gpu_arch = true ;
3751+ graph ->disable_due_to_gpu_arch = true ;
37453752 }
37463753 }
37473754
3748- return cuda_ctx-> cuda_graph ->is_enabled ();
3755+ return graph ->is_enabled ();
37493756#else
37503757 GGML_UNUSED (cuda_ctx);
3758+ GGML_UNUSED (graph_key);
37513759 return false ;
37523760#endif // USE_CUDA_GRAPH
37533761}
@@ -3759,15 +3767,19 @@ static enum ggml_status ggml_backend_cuda_graph_compute(ggml_backend_t backend,
37593767
37603768 bool use_cuda_graph = false ;
37613769 bool cuda_graph_update_required = false ;
3770+ const void * graph_key = nullptr ;
37623771
37633772#ifdef USE_CUDA_GRAPH
3764- use_cuda_graph = ggml_cuda_graph_set_enabled (cuda_ctx);
3773+ graph_key = ggml_cuda_graph_get_key (cgraph);
3774+
3775+ use_cuda_graph = ggml_cuda_graph_set_enabled (cuda_ctx, graph_key);
37653776
3766- if (cuda_ctx->cuda_graph ->is_enabled ()) {
3777+ ggml_cuda_graph * graph = cuda_ctx->cuda_graph (graph_key);
3778+ if (graph->is_enabled ()) {
37673779 cuda_graph_update_required = ggml_cuda_graph_update_required (cuda_ctx, cgraph);
37683780 use_cuda_graph = ggml_cuda_graph_check_compability (cgraph);
37693781
3770- cuda_ctx-> cuda_graph ->record_update (use_cuda_graph, cuda_graph_update_required);
3782+ graph ->record_update (use_cuda_graph, cuda_graph_update_required);
37713783 }
37723784#endif // USE_CUDA_GRAPH
37733785
@@ -3781,7 +3793,7 @@ static enum ggml_status ggml_backend_cuda_graph_compute(ggml_backend_t backend,
37813793 CUDA_CHECK (cudaStreamBeginCapture (cuda_ctx->stream (), cudaStreamCaptureModeRelaxed));
37823794 }
37833795
3784- ggml_cuda_graph_evaluate_and_capture (cuda_ctx, cgraph, use_cuda_graph, cuda_graph_update_required);
3796+ ggml_cuda_graph_evaluate_and_capture (cuda_ctx, cgraph, use_cuda_graph, cuda_graph_update_required, graph_key );
37853797
37863798 return GGML_STATUS_SUCCESS ;
37873799}
@@ -3814,7 +3826,14 @@ static void ggml_backend_cuda_event_wait(ggml_backend_t backend, ggml_backend_ev
38143826static void ggml_backend_cuda_graph_optimize (ggml_backend_t backend, ggml_cgraph * cgraph) {
38153827 ggml_backend_cuda_context * cuda_ctx = (ggml_backend_cuda_context *) backend->context ;
38163828
3817- const bool use_cuda_graph = ggml_cuda_graph_set_enabled (cuda_ctx);
3829+ #ifdef USE_CUDA_GRAPH
3830+ const void * graph_key = ggml_cuda_graph_get_key (cgraph);
3831+ const bool use_cuda_graph = ggml_cuda_graph_set_enabled (cuda_ctx, graph_key);
3832+ #else
3833+ const bool use_cuda_graph = false ;
3834+ GGML_UNUSED (cuda_ctx);
3835+ GGML_UNUSED (cgraph);
3836+ #endif
38183837
38193838 static bool enable_graph_optimization = [] {
38203839 const char * env = getenv (" GGML_CUDA_GRAPH_OPT" );
0 commit comments