Coverage for cuda / core / graph / _utils.pyx: 82.22%
45 statements
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-22 01:37 +0000
« prev ^ index » next coverage.py v7.14.0, created at 2026-05-22 01:37 +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._utils.cuda_utils cimport HANDLE_RETURN
16cdef extern from "Python.h":
17 void _py_decref "Py_DECREF" (void*)
20cdef void _py_host_trampoline(void* data) noexcept with gil:
21 (<object>data)()
24cdef void _py_host_destructor(void* data) noexcept with gil:
25 _py_decref(data) 2d becedeeefegeheiejekelemeneoe@ e [ ] ^ _ ` peqereseteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!e#e$e%e'e(e)e*e+e,e-e.e
28cdef bint _is_py_host_trampoline(cydriver.CUhostFn fn) noexcept nogil:
29 return fn == <cydriver.CUhostFn>_py_host_trampoline
32cdef void _attach_user_object(
33 cydriver.CUgraph graph, void* ptr,
34 cydriver.CUhostFn destroy) except *:
35 """Create a CUDA user object and transfer ownership to the graph.
37 On success the graph owns the resource (via MOVE semantics).
38 On failure the destroy callback is invoked to clean up ptr,
39 then a CUDAError is raised — callers need no try/except.
40 """
41 cdef cydriver.CUuserObject user_obj = NULL 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
42 cdef cydriver.CUresult ret
43 with nogil: 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
44 ret = cydriver.cuUserObjectCreate( 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
45 &user_obj, ptr, destroy, 1,
46 cydriver.CU_USER_OBJECT_NO_DESTRUCTOR_SYNC)
47 if ret == cydriver.CUDA_SUCCESS: 2{ a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
48 ret = cydriver.cuGraphRetainUserObject( 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
49 graph, user_obj, 1, cydriver.CU_GRAPH_USER_OBJECT_MOVE)
50 if ret != cydriver.CUDA_SUCCESS: 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
51 cydriver.cuUserObjectRelease(user_obj, 1)
52 if ret != cydriver.CUDA_SUCCESS: 2a d b | } f n ~ abbbcbdbebfbgbhbibo g jbkblbmbp h nbobpbqbq i rbsbtbubr j vbwbxbybs k zbAbBbCbt l DbEbFbGbHbIbc m JbKbLbMbNbObPbQb@ RbSbTbUbVbWbe [ ] ^ _ ` XbYbZb0b1bu 2b3b4b5bv 6b7b8b9bw !b#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 ~bacbcccD dcecE fcgchcicF jckclcmcncocpcG qcrcscH tcI J K L ucvcwcM xcyczcAcBcN CcDcEcFcGcHcIcJcKcO LcMcNcOcP PcQcRcQ ScTcUcR VcWcXcYcS Zc0c1c2cT 3c4c5c6cU 7c8c9c!cV #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 adbdcddd2 edfd3 gdhdidjd4 kdldmdndodpdqd5 rdsdtd6 ud7 8 9 ! vdwdxd# ydzdAdBdCd$ DdEdFdGdHdIdJdKdLd% MdNdOdPd' QdRdSd( TdUdVd) WdXdYdZd* 0d1d2d3d+ 4d5d6d7d, 8d9d!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? ~d
53 if user_obj == NULL:
54 destroy(ptr)
55 HANDLE_RETURN(ret)
58cdef void _attach_host_callback_to_graph(
59 cydriver.CUgraph graph, object fn, object user_data,
60 cydriver.CUhostFn* out_fn, void** out_user_data) except *:
61 """Resolve a Python callable or ctypes CFuncPtr into a C callback pair.
63 Handles Py_INCREF, user-object attachment for lifetime management,
64 and user_data copying. On return, *out_fn and *out_user_data are
65 ready to pass to cuGraphAddHostNode or cuLaunchHostFunc.
66 """
67 import ctypes as ct 2a d b aef n o g p h q i r j s k t l c m e 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 ! # $ % ' ( ) * + , - . / : ; = ?
69 cdef void* fn_pyobj = NULL 2a d b aef n o g p h q i r j s k t l c m e 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 ! # $ % ' ( ) * + , - . / : ; = ?
71 if isinstance(fn, ct._CFuncPtr): 2a d b aef n o g p h q i r j s k t l c m e 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 ! # $ % ' ( ) * + , - . / : ; = ?
72 Py_INCREF(fn) 1abfghijklcm
73 fn_pyobj = <void*>fn 1abfghijklcm
74 _attach_user_object( 1abfghijklcm
75 graph, fn_pyobj,
76 <cydriver.CUhostFn>_py_host_destructor)
77 out_fn[0] = <cydriver.CUhostFn><uintptr_t>ct.cast( 1abfghijklcm
78 fn, ct.c_void_p).value 1abfghijklcm
80 if user_data is not None: 1abfghijklcm
81 if isinstance(user_data, int): 1abc
82 out_user_data[0] = <void*><uintptr_t>user_data
83 else:
84 buf = bytes(user_data) 1abc
85 out_user_data[0] = malloc(len(buf)) 1abc
86 if out_user_data[0] == NULL: 1abc
87 raise MemoryError(
88 "failed to allocate user_data buffer")
89 c_memcpy(out_user_data[0], <const char*>buf, len(buf)) 1abc
90 _attach_user_object( 1abc
91 graph, out_user_data[0],
92 <cydriver.CUhostFn>free)
93 else:
94 out_user_data[0] = NULL 1fghijklm
95 else:
96 if user_data is not None: 2d aen o p q r s t e 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 ! # $ % ' ( ) * + , - . / : ; = ?
97 raise ValueError( 2d ae
98 "user_data is only supported with ctypes "
99 "function pointers")
100 Py_INCREF(fn) 1dnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
101 fn_pyobj = <void*>fn 1dnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
102 out_fn[0] = <cydriver.CUhostFn>_py_host_trampoline 1dnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
103 out_user_data[0] = fn_pyobj 1dnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
104 _attach_user_object( 1dnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
105 graph, fn_pyobj,
106 <cydriver.CUhostFn>_py_host_destructor)