@@ -1389,6 +1389,12 @@ ggml_backend_buffer_type_t ggml_backend_cuda_host_buffer_type() {
13891389 return &ggml_backend_cuda_buffer_type_host;
13901390}
13911391
1392+ static bool ggml_cuda_buffer_visible_to_backend (ggml_backend_cuda_context * cuda_ctx, ggml_backend_buffer_type_t buft, bool integrated) {
1393+ return buft == ggml_backend_cuda_buffer_type (cuda_ctx->device ) ||
1394+ ggml_backend_buft_is_cuda_split (buft) ||
1395+ (integrated && ggml_backend_buft_is_cuda_host (buft));
1396+ }
1397+
13921398// static bool ggml_backend_buffer_is_cuda_host(ggml_backend_buffer_t buffer) {
13931399// return buffer->buft->iface.get_name == ggml_backend_cuda_host_buffer_type_name;
13941400// }
@@ -3101,54 +3107,87 @@ static void ggml_backend_cuda_synchronize(ggml_backend_t backend) {
31013107 GGML_UNUSED (backend);
31023108}
31033109
3104- static bool ggml_cuda_buffer_visible_to_backend (
3105- ggml_backend_cuda_context * cuda_ctx,
3106- ggml_backend_buffer_type_t buft,
3107- bool integrated) {
3108- return buft == ggml_backend_cuda_buffer_type (cuda_ctx->device ) ||
3109- ggml_backend_buft_is_cuda_split (buft) ||
3110- (integrated && ggml_backend_buft_is_cuda_host (buft));
3111- }
3112-
3113- #ifndef NDEBUG
31143110static void ggml_cuda_log_nonlocal_src_buffer (
31153111 ggml_backend_cuda_context * cuda_ctx,
31163112 const ggml_tensor * node,
3117- int src_idx) {
3118- const ggml_tensor * src = node->src [src_idx];
3113+ int src_index,
3114+ bool integrated,
3115+ const char * action) {
3116+ const ggml_tensor * src = src_index >= 0 ? node->src [src_index] : node;
3117+ const void * data = src ? src->data : nullptr ;
31193118 int ptr_device = -1 ;
3120- int ptr_type = - 1 ;
3119+ const char * ptr_type = " unknown " ;
31213120
3122- if (src && src-> data ) {
3121+ if (data) {
31233122 cudaPointerAttributes attr;
3124- cudaError_t err = cudaPointerGetAttributes (&attr, src-> data );
3123+ cudaError_t err = cudaPointerGetAttributes (&attr, data);
31253124 if (err == cudaSuccess) {
31263125 ptr_device = attr.device ;
31273126#if CUDART_VERSION >= 10000
3128- ptr_type = attr.type ;
3127+ switch ( attr.type ) {
31293128#else
3130- ptr_type = attr.memoryType ;
3129+ switch ( attr.memoryType ) {
31313130#endif
3131+ case cudaMemoryTypeHost: ptr_type = " host" ; break ;
3132+ case cudaMemoryTypeDevice: ptr_type = " device" ; break ;
3133+ case cudaMemoryTypeManaged: ptr_type = " managed" ; break ;
3134+ default : ptr_type = " other" ; break ;
3135+ }
31323136 } else {
3133- ( void ) cudaGetLastError ();
3137+ cudaGetLastError ();
31343138 }
31353139 }
31363140
31373141 GGML_LOG_ERROR (
3138- " %s: source buffer is not visible to CUDA backend device %d: node=%s op=%s src[%d]=%s src_buffer=%s src_ptr=%p ptr_device=%d ptr_type=%d dst_buffer=%s\n " ,
3139- __func__,
3140- cuda_ctx->device ,
3141- node->name ,
3142- ggml_op_name (node->op ),
3143- src_idx,
3144- src ? src->name : " (null)" ,
3145- src && src->buffer ? ggml_backend_buft_name (src->buffer ->buft ) : " (no buffer)" ,
3146- src ? src->data : nullptr ,
3147- ptr_device,
3148- ptr_type,
3149- ggml_backend_buft_name (ggml_backend_cuda_buffer_type (cuda_ctx->device )));
3142+ " %s: source buffer is not visible to CUDA backend device; action=%s backend_device=%d integrated=%d node=%s op=%s src[%d]=%s src_buft=%s dst_buft=%s src_data=%p ptr_type=%s ptr_device=%d\n " ,
3143+ __func__,
3144+ action ? action : " fail" ,
3145+ cuda_ctx->device ,
3146+ integrated ? 1 : 0 ,
3147+ node ? node->name : " (null)" ,
3148+ node ? ggml_op_name (node->op ) : " (null)" ,
3149+ src_index,
3150+ src ? src->name : " (null)" ,
3151+ src && src->buffer ? ggml_backend_buft_name (src->buffer ->buft ) : " (none)" ,
3152+ node && node->buffer ? ggml_backend_buft_name (node->buffer ->buft ) : " (none)" ,
3153+ data,
3154+ ptr_type,
3155+ ptr_device);
3156+ }
3157+
3158+ static bool ggml_cuda_graph_node_buffers_visible (
3159+ ggml_backend_cuda_context * cuda_ctx,
3160+ const ggml_tensor * node,
3161+ bool integrated,
3162+ bool log_errors) {
3163+ if (!node || ggml_is_empty (node) || node->op == GGML_OP_RESHAPE || node->op == GGML_OP_TRANSPOSE ||
3164+ node->op == GGML_OP_VIEW || node->op == GGML_OP_PERMUTE || node->op == GGML_OP_NONE ||
3165+ (node->flags & GGML_TENSOR_FLAG_COMPUTE ) == 0 ) {
3166+ return true ;
3167+ }
3168+
3169+ if (!node->buffer || node->buffer ->buft != ggml_backend_cuda_buffer_type (cuda_ctx->device )) {
3170+ if (log_errors) {
3171+ ggml_cuda_log_nonlocal_src_buffer (cuda_ctx, node, -1 , integrated, " fail graph compute" );
3172+ }
3173+ return false ;
3174+ }
3175+
3176+ for (int j = 0 ; j < GGML_MAX_SRC ; ++j) {
3177+ const ggml_tensor * src = node->src [j];
3178+ if (!src) {
3179+ continue ;
3180+ }
3181+ if (!src->buffer || !ggml_cuda_buffer_visible_to_backend (cuda_ctx, src->buffer ->buft , integrated)) {
3182+ if (log_errors) {
3183+ ggml_cuda_log_nonlocal_src_buffer (cuda_ctx, node, j, integrated, " fail graph compute" );
3184+ }
3185+ return false ;
3186+ }
3187+ }
3188+
3189+ return true ;
31503190}
3151- #endif
31523191
31533192#ifdef USE_CUDA_GRAPH
31543193static bool ggml_cuda_graph_check_compability (ggml_backend_cuda_context * cuda_ctx, ggml_cgraph * cgraph) {
@@ -3169,7 +3208,6 @@ static bool ggml_cuda_graph_check_compability(ggml_backend_cuda_context * cuda_c
31693208 if (!src || !src->buffer ) {
31703209 continue ;
31713210 }
3172-
31733211 const ggml_backend_buffer_type_t src_buft = src->buffer ->buft ;
31743212 if (ggml_backend_buft_is_cuda_split (src_buft)) {
31753213 use_cuda_graph = false ; // Split buffers are not supported by CUDA graph capture
@@ -3189,6 +3227,9 @@ static bool ggml_cuda_graph_check_compability(ggml_backend_cuda_context * cuda_c
31893227 break ;
31903228 }
31913229 }
3230+ if (!use_cuda_graph) {
3231+ break ;
3232+ }
31923233
31933234 // [TAG_MUL_MAT_ID_CUDA_GRAPHS]
31943235 if (node->op == GGML_OP_MUL_MAT_ID ) {
@@ -4128,7 +4169,7 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
41284169}
41294170
41304171
4131- 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) {
4172+ static enum ggml_status 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) {
41324173 bool graph_evaluated_or_captured = false ;
41334174
41344175 // flag used to determine whether it is an integrated_gpu
@@ -4280,34 +4321,15 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
42804321 i += nodes_to_skip;
42814322 continue ;
42824323 }
4283- #ifndef NDEBUG
4284- const ggml_backend_buffer_type_t local_buft = ggml_backend_cuda_buffer_type (cuda_ctx->device );
4285- if (node->buffer ->buft != local_buft) {
4286- GGML_LOG_ERROR (" %s: node buffer is not local to CUDA backend device %d: node=%s op=%s node_buffer=%s dst_buffer=%s\n " ,
4287- __func__, cuda_ctx->device , node->name , ggml_op_name (node->op ),
4288- ggml_backend_buft_name (node->buffer ->buft ), ggml_backend_buft_name (local_buft));
4289- }
4290- assert (node->buffer ->buft == local_buft);
4291- for (int j = 0 ; j < GGML_MAX_SRC ; j++) {
4292- if (node->src [j] != nullptr ) {
4293- assert (node->src [j]->buffer );
4294- const ggml_backend_buffer_type_t src_buft = node->src [j]->buffer ->buft ;
4295- const bool src_visible = ggml_cuda_buffer_visible_to_backend (cuda_ctx, src_buft, integrated);
4296- if (!src_visible) {
4297- ggml_cuda_log_nonlocal_src_buffer (cuda_ctx, node, j);
4298- }
4299- assert (src_visible);
4300- }
4324+ if (!ggml_cuda_graph_node_buffers_visible (cuda_ctx, node, integrated, true )) {
4325+ return GGML_STATUS_FAILED ;
43014326 }
4302- #else
4303- GGML_UNUSED (integrated);
4304- #endif // NDEBUG
43054327
43064328 bool ok = ggml_cuda_compute_forward (*cuda_ctx, node);
43074329 if (!ok) {
43084330 GGML_LOG_ERROR (" %s: op not supported %s (%s)\n " , __func__, node->name , ggml_op_name (node->op ));
4331+ return GGML_STATUS_FAILED ;
43094332 }
4310- GGML_ASSERT (ok);
43114333
43124334 if (!is_concurrent_event_active) {
43134335 try_launch_concurrent_event (node);
@@ -4350,6 +4372,8 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
43504372 graph_evaluated_or_captured = true ;
43514373#endif // USE_CUDA_GRAPH
43524374 }
4375+
4376+ return GGML_STATUS_SUCCESS ;
43534377}
43544378
43554379#ifdef USE_CUDA_GRAPH
@@ -4413,6 +4437,13 @@ static enum ggml_status ggml_backend_cuda_graph_compute(ggml_backend_t backend,
44134437 }
44144438#endif // USE_CUDA_GRAPH
44154439
4440+ const bool integrated = ggml_cuda_info ().devices [cuda_ctx->device ].integrated ;
4441+ for (int i = 0 ; i < cgraph->n_nodes ; ++i) {
4442+ if (!ggml_cuda_graph_node_buffers_visible (cuda_ctx, cgraph->nodes [i], integrated, true )) {
4443+ return GGML_STATUS_FAILED ;
4444+ }
4445+ }
4446+
44164447 if (use_cuda_graph && cuda_graph_update_required) {
44174448 // Start CUDA graph capture
44184449 {
@@ -4423,7 +4454,10 @@ static enum ggml_status ggml_backend_cuda_graph_compute(ggml_backend_t backend,
44234454 CUDA_CHECK (cudaStreamBeginCapture (cuda_ctx->stream (), cudaStreamCaptureModeRelaxed));
44244455 }
44254456
4426- ggml_cuda_graph_evaluate_and_capture (cuda_ctx, cgraph, use_cuda_graph, cuda_graph_update_required, graph_key);
4457+ const ggml_status status = ggml_cuda_graph_evaluate_and_capture (cuda_ctx, cgraph, use_cuda_graph, cuda_graph_update_required, graph_key);
4458+ if (status != GGML_STATUS_SUCCESS ) {
4459+ return status;
4460+ }
44274461
44284462 return GGML_STATUS_SUCCESS ;
44294463}
0 commit comments