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
« 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
5from cpython.ref cimport Py_INCREF
7from libc.stdint cimport uintptr_t
8from libc.stdlib cimport malloc, free
9from libc.string cimport memcpy as c_memcpy
11from cuda.bindings cimport cydriver
13from cuda.core._resource_handles cimport py_object_user_object_destroy
14from cuda.core._utils.cuda_utils cimport HANDLE_RETURN
17cdef void _py_host_trampoline(void* data) noexcept with gil:
18 (<object>data)()
21cdef bint _is_py_host_trampoline(cydriver.CUhostFn fn) noexcept nogil:
22 return fn == <cydriver.CUhostFn>_py_host_trampoline
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.
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)
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.
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 ! # $ % ' ( ) * + , - . / : ; = ?
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 ! # $ % ' ( ) * + , - . / : ; = ?
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
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)