Coverage for cuda / core / graph / _utils.pyx: 82.22%
45 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-29 01:27 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-29 01:27 +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) 2~daebecedeeefegeheiejekeled @ e meneoepeqereseteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e7e8e9e!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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b ] ^ g n _ ` { | } ~ abbbcbdbo h ebfbgbhbp i ibjbkblbq j mbnbobpbr k qbrbsbtbs l ubvbwbxbt m ybzbAbBbCbDbc d @ EbFbGbHbIbJbKbLbMbNbObPbe QbRbSbTbUbVbWbXbYbZbu 0b1b2b3bv 4b5b6b7bw 8b9b!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}b~bacD bcccE dcecfcgcF hcicjckclcmcncG ocpcqcH rcI J K L sctcucM vcwcxcyczcN AcBcCcDcEcFcGcHcIcO JcKcLcMcP NcOcPcQ QcRcScR TcUcVcWcS XcYcZc0cT 1c2c3c4cU 5c6c7c8cV 9c!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 }c~cadbd2 cddd3 edfdgdhd4 idjdkdldmdndod5 pdqdrd6 sd7 8 9 ! tdudvd# wdxdydzdAd$ BdCdDdEdFdGdHdIdJd% KdLdMdNd' OdPdQd( RdSdTd) UdVdWdXd* YdZd0d1d+ 2d3d4d5d, 6d7d8d9d- !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 f b }dg n o h p i q j r k s l t m c d 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 f b }dg n o h p i q j r k s l t m c d 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 f b }dg n o h p i q j r k s l t m c d 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) 1abghijklmcd
73 fn_pyobj = <void*>fn 1abghijklmcd
74 _attach_user_object( 1abghijklmcd
75 graph, fn_pyobj,
76 <cydriver.CUhostFn>_py_host_destructor)
77 out_fn[0] = <cydriver.CUhostFn><uintptr_t>ct.cast( 1abghijklmcd
78 fn, ct.c_void_p).value 1abghijklmcd
80 if user_data is not None: 1abghijklmcd
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 1ghijklmd
95 else:
96 if user_data is not None: 2f }dn 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( 2f }d
98 "user_data is only supported with ctypes "
99 "function pointers")
100 Py_INCREF(fn) 1fnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
101 fn_pyobj = <void*>fn 1fnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
102 out_fn[0] = <cydriver.CUhostFn>_py_host_trampoline 1fnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
103 out_user_data[0] = fn_pyobj 1fnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
104 _attach_user_object( 1fnopqrsteuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?
105 graph, fn_pyobj,
106 <cydriver.CUhostFn>_py_host_destructor)