Coverage for cuda/core/graph/_utils.pyx: 83.72%

43 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-13 01:38 +0000

1# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from cpython.ref cimport Py_INCREF 

6  

7from libc.stdint cimport uintptr_t 

8from libc.stdlib cimport malloc, free 

9from libc.string cimport memcpy as c_memcpy 

10  

11from cuda.bindings cimport cydriver 

12  

13from cuda.core._resource_handles cimport py_object_user_object_destroy 

14from cuda.core._utils.cuda_utils cimport HANDLE_RETURN 

15  

16  

17cdef void _py_host_trampoline(void* data) noexcept with gil: 

18 (<object>data)() 

19  

20  

21cdef bint _is_py_host_trampoline(cydriver.CUhostFn fn) noexcept nogil: 

22 return fn == <cydriver.CUhostFn>_py_host_trampoline 

23  

24  

25cdef void _attach_user_object( 

26 cydriver.CUgraph graph, void* ptr, 

27 cydriver.CUhostFn destroy) except *: 

28 """Create a CUDA user object and transfer ownership to the graph. 

29  

30 On success the graph owns the resource (via MOVE semantics). 

31 On failure the destroy callback is invoked to clean up ptr, 

32 then a CUDAError is raised — callers need no try/except. 

33 """ 

34 cdef cydriver.CUuserObject user_obj = NULL 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

35 cdef cydriver.CUresult ret 

36 with nogil: 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

37 ret = cydriver.cuUserObjectCreate( 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

38 &user_obj, ptr, destroy, 1, 

39 cydriver.CU_USER_OBJECT_NO_DESTRUCTOR_SYNC) 

40 if ret == cydriver.CUDA_SUCCESS: 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

41 ret = cydriver.cuGraphRetainUserObject( 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

42 graph, user_obj, 1, cydriver.CU_GRAPH_USER_OBJECT_MOVE) 

43 if ret != cydriver.CUDA_SUCCESS: 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

44 cydriver.cuUserObjectRelease(user_obj, 1) 

45 if ret != cydriver.CUDA_SUCCESS: 2a d b @ [ e m ] ^ _ ` { | } ~ abbbn f cbdbebfbo g gbhbibjbp h kblbmbnbq i obpbqbrbr j sbtbubvbs k wbxbybzbAbBbc l CbDbEbFbGbHbIbJbKbLbMbNbObPbQbt RbSbTbUbVbWbXbYbZb0bu 1b2b3b4bv 5b6b7b8bw 9b!b#b$bx %b'b(by )b*b+b,b-b.b/bz :b;b=b?bA @b[b]b^bB _b`b{b|bC }b~bacbcD ccdcE ecfcgchcF icjckclcmcncocG pcqcrcH scI J K L tcucvcM wcxcyczcAcN BcCcDcEcFcGcHcIcJcO KcLcMcNcP OcPcQcQ RcScTcR UcVcWcXcS YcZc0c1cT 2c3c4c5cU 6c7c8c9cV !c#c$c%cW 'c(c)cX *c+c,c-c.c/c:cY ;c=c?c@cZ [c]c^c_c0 `c{c|c}c1 ~cadbdcd2 dded3 fdgdhdid4 jdkdldmdndodpd5 qdrdsd6 td7 8 9 ! udvdwd# xdydzdAdBd$ CdDdEdFdGdHdIdJdKd% LdMdNdOd' PdQdRd( SdTdUd) VdWdXdYd* Zd0d1d2d+ 3d4d5d6d, 7d8d9d!d- #d$d%d'd. (d)d*d+d/ ,d-d.d/d: :d;d=d?d; @d[d]d^d= _d`d{d|d? }d

46 if user_obj == NULL: 

47 destroy(ptr) 

48 HANDLE_RETURN(ret) 

49  

50  

51cdef void _attach_host_callback_to_graph( 

52 cydriver.CUgraph graph, object fn, object user_data, 

53 cydriver.CUhostFn* out_fn, void** out_user_data) except *: 

54 """Resolve a Python callable or ctypes CFuncPtr into a C callback pair. 

55  

56 Handles Py_INCREF, user-object attachment for lifetime management, 

57 and user_data copying. On return, *out_fn and *out_user_data are 

58 ready to pass to cuGraphAddHostNode or cuLaunchHostFunc. 

59 """ 

60 import ctypes as ct 2a d b aee m n f o g p h q i r j s k c l t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ?

61  

62 cdef void* fn_pyobj = NULL 2a d b aee m n f o g p h q i r j s k c l t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ?

63  

64 if isinstance(fn, ct._CFuncPtr): 2a d b aee m n f o g p h q i r j s k c l t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ?

65 Py_INCREF(fn) 1abefghijkcl

66 fn_pyobj = <void*>fn 1abefghijkcl

67 _attach_user_object( 1abefghijkcl

68 graph, fn_pyobj, 

69 <cydriver.CUhostFn>py_object_user_object_destroy) 

70 out_fn[0] = <cydriver.CUhostFn><uintptr_t>ct.cast( 1abefghijkcl

71 fn, ct.c_void_p).value 1abefghijkcl

72  

73 if user_data is not None: 1abefghijkcl

74 if isinstance(user_data, int): 1abc

75 out_user_data[0] = <void*><uintptr_t>user_data 

76 else: 

77 buf = bytes(user_data) 1abc

78 out_user_data[0] = malloc(len(buf)) 1abc

79 if out_user_data[0] == NULL: 1abc

80 raise MemoryError( 

81 "failed to allocate user_data buffer") 

82 c_memcpy(out_user_data[0], <const char*>buf, len(buf)) 1abc

83 _attach_user_object( 1abc

84 graph, out_user_data[0], 

85 <cydriver.CUhostFn>free) 

86 else: 

87 out_user_data[0] = NULL 1efghijkl

88 else: 

89 if user_data is not None: 2d aem n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , - . / : ; = ?

90 raise ValueError( 2d ae

91 "user_data is only supported with ctypes " 

92 "function pointers") 

93 Py_INCREF(fn) 1dmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?

94 fn_pyobj = <void*>fn 1dmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?

95 out_fn[0] = <cydriver.CUhostFn>_py_host_trampoline 1dmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?

96 out_user_data[0] = fn_pyobj 1dmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?

97 _attach_user_object( 1dmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?

98 graph, fn_pyobj, 

99 <cydriver.CUhostFn>py_object_user_object_destroy)