Coverage for cuda / core / _event.pyx: 85.59%

118 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-03-25 01:07 +0000

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

2# 

3# SPDX-License-Identifier: Apache-2.0 

4  

5from __future__ import annotations 

6  

7cimport cpython 

8from libc.string cimport memcpy 

9from cuda.bindings cimport cydriver 

10from cuda.core._context cimport Context 

11from cuda.core._resource_handles cimport ( 

12 ContextHandle, 

13 EventHandle, 

14 create_event_handle, 

15 create_event_handle_ipc, 

16 get_event_timing_disabled, 

17 get_event_busy_waited, 

18 get_event_ipc_enabled, 

19 get_event_device_id, 

20 get_event_context, 

21 as_intptr, 

22 as_cu, 

23 as_py, 

24) 

25  

26from cuda.core._utils.cuda_utils cimport ( 

27 check_or_create_options, 

28 HANDLE_RETURN 

29) 

30  

31import cython 

32from dataclasses import dataclass 

33import multiprocessing 

34  

35from cuda.core._utils.cuda_utils import ( 

36 CUDAError, 

37 check_multiprocessing_start_method, 

38) 

39  

40  

41@dataclass 

42cdef class EventOptions: 

43 """Customizable :obj:`~_event.Event` options. 

44  

45 Attributes 

46 ---------- 

47 enable_timing : bool, optional 

48 Event will record timing data. (Default to False) 

49 busy_waited_sync : bool, optional 

50 If True, event will use blocking synchronization. When a CPU 

51 thread calls synchronize, the call will block until the event 

52 has actually been completed. 

53 Otherwise, the CPU thread will busy-wait until the event has 

54 been completed. (Default to False) 

55 ipc_enabled : bool, optional 

56 Event will be suitable for interprocess use. 

57 Note that enable_timing must be False. (Default to False) 

58  

59 """ 

60  

61 enable_timing: bool | None = False 

62 busy_waited_sync: bool | None = False 

63 ipc_enabled: bool | None = False 

64  

65  

66cdef class Event: 

67 """Represent a record at a specific point of execution within a CUDA stream. 

68  

69 Applications can asynchronously record events at any point in 

70 the program. An event keeps a record of all previous work within 

71 the last recorded stream. 

72  

73 Events can be used to monitor device's progress, query completion 

74 of work up to event's record, help establish dependencies 

75 between GPU work submissions, and record the elapsed time (in milliseconds) 

76 on GPU: 

77  

78 .. code-block:: python 

79  

80 # To create events and record the timing: 

81 s = Device().create_stream() 

82 e1 = Device().create_event({"enable_timing": True}) 

83 e2 = Device().create_event({"enable_timing": True}) 

84 s.record(e1) 

85 # ... run some GPU works ... 

86 s.record(e2) 

87 e2.sync() 

88 print(f"time = {e2 - e1} milliseconds") 

89  

90 Directly creating an :obj:`~_event.Event` is not supported due to ambiguity, 

91 and they should instead be created through a :obj:`~_stream.Stream` object. 

92  

93 """ 

94  

95 def __init__(self, *args, **kwargs): 

96 raise RuntimeError("Event objects cannot be instantiated directly. Please use Stream APIs (record).") 2?c

97  

98 @staticmethod 

99 cdef Event _init(type cls, int device_id, ContextHandle h_context, options, bint is_free): 

100 cdef Event self = cls.__new__(cls) 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

101 cdef EventOptions opts = check_or_create_options(EventOptions, options, "Event options") 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

102 cdef unsigned int flags = 0x0 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

103 cdef bint timing_disabled = False 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

104 cdef bint busy_waited = False 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

105 cdef bint ipc_enabled = False 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

106 self._ipc_descriptor = None 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

107 if not opts.enable_timing: 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

108 flags |= cydriver.CUevent_flags.CU_EVENT_DISABLE_TIMING 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObs PbQbt q Rb_ i j e a f b g c h d n ` r y Sbz { F | A G } K B H w k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

109 timing_disabled = True 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObs PbQbt q Rb_ i j e a f b g c h d n ` r y Sbz { F | A G } K B H w k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

110 if opts.busy_waited_sync: 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

111 flags |= cydriver.CUevent_flags.CU_EVENT_BLOCKING_SYNC 1poabcdH

112 busy_waited = True 1poabcdH

113 if opts.ipc_enabled: 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n -c.c` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

114 if is_free: 2i j e a f b g c h d n -c.ck l m

115 raise TypeError( 1Jn

116 "IPC-enabled events must be bound; use Stream.record for creation." 

117 ) 

118 flags |= cydriver.CUevent_flags.CU_EVENT_INTERPROCESS 2i j e a f b g c h d n -c.ck l m

119 ipc_enabled = True 2i j e a f b g c h d n -c.ck l m

120 if not timing_disabled: 2i j e a f b g c h d n -c.ck l m

121 raise TypeError("IPC-enabled events cannot use timing.") 2-c.c

122 cdef EventHandle h_event = create_event_handle( 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n ` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

123 h_context, flags, timing_disabled, busy_waited, ipc_enabled, device_id) 

124 if not h_event: 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n ` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

125 raise RuntimeError("Failed to create CUDA event") 

126 self._h_event = h_event 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n ` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

127 if ipc_enabled: 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n ` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

128 self.get_ipc_descriptor() 1ijeafbgchdnklm

129 return self 29 ! # $ % ' ( ) * + , - . / : ; = ? @ [ ] ^ CbDbEbFbGbHbIbJbKbLbMbNbObp s o PbQbt q Rb_ i j e a f b g c h d n ` r u v y Sbz { F | A G } K B H w C k x TbUb~ VbWbXbYbZb0b1b2b3b4b5b6bab7b8b9b!bbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb#b$b%b'b(b)b*b+b,b-b.b/b:b;b=b?b@b[b]b^b_b`b{b|b}b~bacbcccxbdcecybfcgchcicjckclcmcncocpcqcL rcsctcucM N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 vcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXc8 YcZcl m zb0c1cI 2c3cAb4c5cBb6c7cD 8c9cE !c#c$c%c'c(c)c*c+c,c

130  

131 @staticmethod 

132 cdef Event _from_handle(EventHandle h_event): 

133 """Create an Event wrapping an existing EventHandle. 

134  

135 Metadata (timing, busy_waited, ipc, device_id) is read from the 

136 EventBox via pointer arithmetic — no fields are cached on Event. 

137 """ 

138 cdef Event self = Event.__new__(Event) 2/c:c;c=cp s o t q

139 self._h_event = h_event 2/c:c;c=cp s o t q

140 self._ipc_descriptor = None 2/c:c;c=cp s o t q

141 return self 2/c:c;c=cp s o t q

142  

143 cpdef close(self): 

144 """Destroy the event. 

145  

146 Releases the event handle. The underlying CUDA event is destroyed 

147 when the last reference is released. 

148 """ 

149 self._h_event.reset() 19!#$%'()*+,-./:;=?@[]^_k

150  

151 def __isub__(self, other): 

152 return NotImplemented 

153  

154 def __rsub__(self, other): 

155 return NotImplemented 

156  

157 def __sub__(self, other: Event): 

158 # return self - other (in milliseconds) 

159 cdef float timing 

160 with nogil: 1ruvC

161 err = cydriver.cuEventElapsedTime(&timing, as_cu((<Event>other)._h_event), as_cu(self._h_event)) 1ruvC

162 if err == 0: 1ruvC

163 return timing 1uC

164 else: 

165 if err == cydriver.CUresult.CUDA_ERROR_INVALID_HANDLE: 1ruv

166 if self.is_timing_disabled or other.is_timing_disabled: 1rv

167 explanation = ( 

168 "Both Events must be created with timing enabled in order to subtract them; " 1r

169 "use EventOptions(enable_timing=True) when creating both events." 

170 ) 

171 else: 

172 explanation = ( 

173 "Both Events must be recorded before they can be subtracted; " 1v

174 "use Stream.record() to record both events to a stream." 

175 ) 

176 elif err == cydriver.CUresult.CUDA_ERROR_NOT_READY: 1ruv

177 explanation = ( 

178 "One or both events have not completed; " 1u

179 "use Event.sync(), Stream.sync(), or Device.sync() to wait for the events to complete " 

180 "before subtracting them." 

181 ) 

182 else: 

183 raise CUDAError(err) 

184 raise RuntimeError(explanation) 1ruv

185  

186 def __hash__(self) -> int: 

187 return hash(as_intptr(self._h_event)) 2{ | A } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybAbBbD E

188  

189 def __eq__(self, other) -> bool: 

190 # Note: using isinstance because `Event` can be subclassed. 

191 if not isinstance(other, Event): 2/c:c;c=cF A G K x L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 I D E

192 return NotImplemented 1KxLMNOPQRSTUVWXYZ012345678

193 cdef Event _other = <Event>other 2/c:c;c=cF A G x I D E

194 return as_intptr(self._h_event) == as_intptr(_other._h_event) 2/c:c;c=cF A G x I D E

195  

196 def __repr__(self) -> str: 

197 return f"<Event handle={as_intptr(self._h_event):#x}>" 2i j e a f b g c h d zb

198  

199 def get_ipc_descriptor(self) -> IPCEventDescriptor: 

200 """Export an event allocated for sharing between processes.""" 

201 if self._ipc_descriptor is not None: 1ijeafbgchdnklm

202 return self._ipc_descriptor 1ijeafbgchdklm

203 if not self.is_ipc_enabled: 1ijeafbgchdnklm

204 raise RuntimeError("Event is not IPC-enabled") 

205 cdef cydriver.CUipcEventHandle data 

206 with nogil: 1ijeafbgchdnklm

207 HANDLE_RETURN(cydriver.cuIpcGetEventHandle(&data, as_cu(self._h_event))) 1ijeafbgchdnklm

208 cdef bytes data_b = cpython.PyBytes_FromStringAndSize(<char*>(data.reserved), sizeof(data.reserved)) 1ijeafbgchdnklm

209 self._ipc_descriptor = IPCEventDescriptor._init(data_b, get_event_busy_waited(self._h_event)) 1ijeafbgchdnklm

210 return self._ipc_descriptor 1ijeafbgchdnklm

211  

212 @classmethod 

213 def from_ipc_descriptor(cls, ipc_descriptor: IPCEventDescriptor) -> Event: 

214 """Import an event that was exported from another process.""" 

215 cdef cydriver.CUipcEventHandle data 

216 memcpy(data.reserved, <const void*><const char*>(ipc_descriptor._reserved), sizeof(data.reserved)) 

217 cdef Event self = Event.__new__(cls) 

218 cdef EventHandle h_event = create_event_handle_ipc(data, ipc_descriptor._busy_waited) 

219 if not h_event: 

220 raise RuntimeError("Failed to open IPC event handle") 

221 self._h_event = h_event 

222 self._ipc_descriptor = ipc_descriptor 

223 return self 

224  

225 @property 

226 def is_ipc_enabled(self) -> bool: 

227 """Return True if the event can be shared across process boundaries, otherwise False.""" 

228 return get_event_ipc_enabled(self._h_event) 1oijeafbgchdnklm

229  

230 @property 

231 def is_timing_disabled(self) -> bool: 

232 """Return True if the event does not record timing data, otherwise False.""" 

233 return get_event_timing_disabled(self._h_event) 1poqeafbgchdrv

234  

235 @property 

236 def is_sync_busy_waited(self) -> bool: 

237 """Return True if the event synchronization would keep the CPU busy-waiting, otherwise False.""" 

238 return get_event_busy_waited(self._h_event) 1poqeafbgchdH

239  

240 def sync(self): 

241 """Synchronize until the event completes. 

242  

243 If the event was created with busy_waited_sync, then the 

244 calling CPU thread will block until the event has been 

245 completed by the device. 

246 Otherwise the CPU thread will busy-wait until the event 

247 has been completed. 

248  

249 """ 

250 with nogil: 1uwC

251 HANDLE_RETURN(cydriver.cuEventSynchronize(as_cu(self._h_event))) 1uwC

252  

253 @property 

254 def is_done(self) -> bool: 

255 """Return True if all captured works have been completed, otherwise False.""" 

256 with nogil: 1pstBw

257 result = cydriver.cuEventQuery(as_cu(self._h_event)) 1pstBw

258 if result == cydriver.CUresult.CUDA_SUCCESS: 1pstBw

259 return True 1pstBw

260 if result == cydriver.CUresult.CUDA_ERROR_NOT_READY: 

261 return False 

262 HANDLE_RETURN(result) 

263  

264 @property 

265 def handle(self) -> cuda.bindings.driver.CUevent: 

266 """Return the underlying CUevent object. 

267  

268 .. caution:: 

269  

270 This handle is a Python object. To get the memory address of the underlying C 

271 handle, call ``int(Event.handle)``. 

272 """ 

273 return as_py(self._h_event) 1ij`x

274  

275 @property 

276 def device(self) -> Device: 

277 """Return the :obj:`~_device.Device` singleton associated with this event. 

278  

279 Note 

280 ---- 

281 The current context on the device may differ from this 

282 event's context. This case occurs when a different CUDA 

283 context is set current after a event is created. 

284  

285 """ 

286 cdef int dev_id = get_event_device_id(self._h_event) 1oqz

287 if dev_id >= 0: 1oqz

288 from ._device import Device # avoid circular import 1oqz

289 return Device(dev_id) 1oqz

290  

291 @property 

292 def context(self) -> Context: 

293 """Return the :obj:`~_context.Context` associated with this event.""" 

294 cdef ContextHandle h_ctx = get_event_context(self._h_event) 1y

295 cdef int dev_id = get_event_device_id(self._h_event) 1y

296 if h_ctx and dev_id >= 0: 1y

297 return Context._from_handle(Context, h_ctx, dev_id) 1y

298  

299  

300cdef class IPCEventDescriptor: 

301 """Serializable object describing an event that can be shared between processes.""" 

302  

303 cdef: 

304 bytes _reserved 

305 bint _busy_waited 

306  

307 def __init__(self, *arg, **kwargs): 

308 raise RuntimeError("IPCEventDescriptor objects cannot be instantiated directly. Please use Event APIs.") 

309  

310 @staticmethod 

311 def _init(reserved: bytes, busy_waited: cython.bint): 

312 cdef IPCEventDescriptor self = IPCEventDescriptor.__new__(IPCEventDescriptor) 1ijeafbgchdnklm

313 self._reserved = reserved 1ijeafbgchdnklm

314 self._busy_waited = busy_waited 1ijeafbgchdnklm

315 return self 1ijeafbgchdnklm

316  

317 def __eq__(self, IPCEventDescriptor rhs): 

318 # No need to check self._busy_waited. 

319 return self._reserved == rhs._reserved 1eafbgchd

320  

321 def __reduce__(self): 

322 return IPCEventDescriptor._init, (self._reserved, self._busy_waited) 1ijeafbgchdlm

323  

324  

325def _reduce_event(event): 

326 check_multiprocessing_start_method() 1ijeafbgchdk

327 return event.from_ipc_descriptor, (event.get_ipc_descriptor(),) 1ijeafbgchdk

328  

329multiprocessing.reduction.register(Event, _reduce_event)