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

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._utils.cuda_utils cimport HANDLE_RETURN 

14  

15  

16cdef extern from "Python.h": 

17 void _py_decref "Py_DECREF" (void*) 

18  

19  

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

21 (<object>data)() 

22  

23  

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

26  

27  

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

29 return fn == <cydriver.CUhostFn>_py_host_trampoline 

30  

31  

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. 

36  

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) 

56  

57  

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. 

62  

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 ! # $ % ' ( ) * + , - . / : ; = ?

68  

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 ! # $ % ' ( ) * + , - . / : ; = ?

70  

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

79  

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)