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

146 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-03 02:41 +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.stddef cimport size_t 

9from libc.string cimport memcpy 

10from cuda.bindings cimport cydriver 

11from cuda.core._context cimport Context 

12from cuda.core._resource_handles cimport ( 

13 ContextHandle, 

14 EventHandle, 

15 create_event_handle, 

16 create_event_handle_ipc, 

17 get_event_timing_enabled, 

18 get_event_is_blocking_sync, 

19 get_event_ipc_enabled, 

20 get_event_device_id, 

21 get_event_context, 

22 as_intptr, 

23 as_cu, 

24 as_py, 

25) 

26  

27from cuda.core._utils.cuda_utils cimport ( 

28 check_or_create_options, 

29 HANDLE_RETURN 

30) 

31  

32import cython 

33from dataclasses import dataclass 

34import multiprocessing 

35from typing import TYPE_CHECKING 

36  

37from cuda.core._utils.cuda_utils import ( 

38 CUDAError, 

39 check_multiprocessing_start_method, 

40) 

41  

42if TYPE_CHECKING: 

43 import cuda.bindings.driver # no-cython-lint 

44 from cuda.core._device import Device 

45  

46__all__ = ['Event', 'EventOptions'] 

47  

48  

49@dataclass 

50cdef class EventOptions: 

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

52  

53 Attributes 

54 ---------- 

55 timing_enabled : bool, optional 

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

57 blocking_sync : bool, optional 

58 If True, the event uses blocking synchronization: a CPU 

59 thread that calls :meth:`Event.sync` blocks (yields) until 

60 the event has completed. Otherwise (the default), the CPU 

61 thread busy-waits until the event has completed. 

62 (Default to False) 

63 ipc_enabled : bool, optional 

64 Event will be suitable for interprocess use. 

65 Note that timing_enabled must be False. (Default to False) 

66  

67 """ 

68  

69 timing_enabled: bool | None = False 

70 blocking_sync: bool | None = False 

71 ipc_enabled: bool | None = False 

72  

73  

74cdef class Event: 

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

76  

77 Applications can asynchronously record events at any point in 

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

79 the last recorded stream. 

80  

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

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

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

84 on GPU: 

85  

86 .. code-block:: python 

87  

88 # To create events and record the timing: 

89 s = Device().create_stream() 

90 e1 = Device().create_event({"timing_enabled": True}) 

91 e2 = Device().create_event({"timing_enabled": True}) 

92 s.record(e1) 

93 # ... run some GPU works ... 

94 s.record(e2) 

95 e2.sync() 

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

97  

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

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

100  

101 """ 

102  

103 def __init__(self, *args, **kwargs) -> None: 

104 raise RuntimeError("Event objects cannot be instantiated directly. Please use Stream APIs (record).") 2Wd

105  

106 @staticmethod 

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

108 cdef Event self = cls.__new__(cls) 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

109 cdef EventOptions opts = check_or_create_options(EventOptions, options, "Event options") 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

110 cdef unsigned int flags = 0x0 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

111 cdef bint timing_enabled = True 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

112 cdef bint is_blocking_sync = False 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

113 cdef bint ipc_enabled = False 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

114 self._ipc_descriptor = None 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

115 if not opts.timing_enabled: 2H 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 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

116 flags |= cydriver.CUevent_flags.CU_EVENT_DISABLE_TIMING 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbz ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o 9 hb! : ( ; $ ) I B = ? @ * % # F G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

117 timing_enabled = False 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbz ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o 9 hb! : ( ; $ ) I B = ? @ * % # F G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

118 if opts.blocking_sync: 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

119 flags |= cydriver.CUevent_flags.CU_EVENT_BLOCKING_SYNC 1wpabcd%

120 is_blocking_sync = True 1wpabcd%

121 if opts.ipc_enabled: 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k dded/ t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

122 if is_free: 2i j e a f b g c h d k ddedl m n

123 raise TypeError( 1k

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

125 ) 

126 flags |= cydriver.CUevent_flags.CU_EVENT_INTERPROCESS 2i j e a f b g c h d k ddedl m n

127 ipc_enabled = True 2i j e a f b g c h d k ddedl m n

128 if timing_enabled: 2i j e a f b g c h d k ddedl m n

129 raise TypeError("IPC-enabled events cannot use timing.") 2dded

130 cdef EventHandle h_event = create_event_handle( 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

131 h_context, flags, timing_enabled, is_blocking_sync, ipc_enabled, device_id) 

132 if not h_event: 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

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

134 self._h_event = h_event 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

135 if ipc_enabled: 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

136 _ = self.ipc_descriptor # eagerly populate the descriptor cache 1ijeafbgchdklmn

137 return self 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 [ ] ^ _ ` { | } ~ abbbcbdbw z p ebfbA x gbq C + , - . r D s E 8 i j e a f b g c h d k / t o u v 9 hb! : ( ; $ ) I B = ? @ * % # F y G l ibjbkblbmbnbobpbqbrbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbIbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbZb0b1b2b3b4b5b6b7b8b9b!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}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrcsctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcUcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'cm n (c)c*c+c,c-c.c/c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcd'

138  

139 @staticmethod 

140 cdef Event _from_handle(EventHandle h_event): 

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

142  

143 Metadata (timing, blocking_sync, ipc, device_id) is read from 

144 the EventBox via pointer arithmetic — no fields are cached on 

145 Event. 

146 """ 

147 cdef Event self = Event.__new__(Event) 2gdhdidjdw z p A x q C r D s E

148 self._h_event = h_event 2gdhdidjdw z p A x q C r D s E

149 self._ipc_descriptor = None 2gdhdidjdw z p A x q C r D s E

150 return self 2gdhdidjdw z p A x q C r D s E

151  

152 cpdef close(self): 

153 """Destroy the event. 

154  

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

156 when the last reference is released. 

157 """ 

158 self._h_event.reset() 2J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 q C + , - . r D s E 8 t l ud

159  

160 @property 

161 def is_closed(self) -> bool: 

162 """Whether this event has been closed.""" 

163 return self._h_event.get() == NULL 2t ud

164  

165 def __isub__(self, other: object): 

166 return NotImplemented 1=

167  

168 def __rsub__(self, other: object): 

169 return NotImplemented 1?

170  

171 def __sub__(self, other: Event) -> float: 

172 # return self - other (in milliseconds) 

173 Event_check_open(self) 1touvy

174 cdef Event other_event = Event_accept(other) 1touvy

175 cdef float timing 

176 with nogil: 1ouvy

177 err = cydriver.cuEventElapsedTime(&timing, as_cu(other_event._h_event), as_cu(self._h_event)) 1ouvy

178 if err == 0: 1ouvy

179 return timing 1uy

180 else: 

181 if err == cydriver.CUresult.CUDA_ERROR_INVALID_HANDLE: 1ouv

182 if not self.is_timing_enabled or not other_event.is_timing_enabled: 1ov

183 explanation = ( 

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

185 "use EventOptions(timing_enabled=True) when creating both events." 

186 ) 

187 else: 

188 explanation = ( 

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

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

191 ) 

192 elif err == cydriver.CUresult.CUDA_ERROR_NOT_READY: 1ouv

193 explanation = ( 

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

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

196 "before subtracting them." 

197 ) 

198 else: 

199 raise CUDAError(err) 

200 raise RuntimeError(explanation) 1ouv

201  

202 def __hash__(self) -> int: 

203 return hash(as_intptr(self._h_event)) 2: ; $ @ XdYdZd0d1d2d3d4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,d-d.d/d:d;dvdwd

204  

205 def __eq__(self, other: object) -> bool: 

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

207 if not isinstance(other, Event): 2gdhdidjdq C r D s E ( $ ) * rdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdxdvdwd

208 return NotImplemented 2* rdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVd

209 cdef Event _other = <Event>other 2gdhdidjdq C r D s E ( $ ) rdxdvdwd

210 return as_intptr(self._h_event) == as_intptr(_other._h_event) 2gdhdidjdq C r D s E ( $ ) rdxdvdwd

211  

212 def __repr__(self) -> str: 

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

214  

215 @property 

216 def ipc_descriptor(self) -> IPCEventDescriptor: 

217 """Descriptor for sharing this event with other processes.""" 

218 Event_check_open(self) 1ijeafbgchdktIlmn

219 if self._ipc_descriptor is not None: 1ijeafbgchdkIlmn

220 return self._ipc_descriptor 1ijeafbgchdlmn

221 if not self.is_ipc_enabled: 1ijeafbgchdkIlmn

222 raise RuntimeError("Event is not IPC-enabled") 1I

223 cdef cydriver.CUipcEventHandle data 

224 with nogil: 1ijeafbgchdklmn

225 HANDLE_RETURN(cydriver.cuIpcGetEventHandle(&data, as_cu(self._h_event))) 1ijeafbgchdklmn

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

227 self._ipc_descriptor = IPCEventDescriptor._init(data_b, get_event_is_blocking_sync(self._h_event)) 1ijeafbgchdklmn

228 return self._ipc_descriptor 1ijeafbgchdklmn

229  

230 @classmethod 

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

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

233  

234 Parameters 

235 ---------- 

236 ipc_descriptor : :obj:`~_memory._ipc.IPCEventDescriptor` 

237 The IPC descriptor obtained from :attr:`~Event.ipc_descriptor` in 

238 another process. 

239  

240 Returns 

241 ------- 

242 :obj:`~_event.Event` 

243 A new event backed by the imported IPC handle. 

244  

245 """ 

246 cdef size_t reserved_size = len(ipc_descriptor._reserved) 2fd

247 cdef size_t expected_size = sizeof(cydriver.CUipcEventHandle) 2fd

248 if reserved_size < expected_size: 2fd

249 raise ValueError( 2fd

250 f"IPC event descriptor reserved field is {reserved_size} bytes; " 2fd

251 f"expected at least {expected_size}" 2fd

252 ) 

253 cdef cydriver.CUipcEventHandle data 

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

255 cdef Event self = Event.__new__(cls) 

256 cdef EventHandle h_event = create_event_handle_ipc(data, ipc_descriptor._is_blocking_sync) 

257 if not h_event: 

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

259 self._h_event = h_event 

260 self._ipc_descriptor = ipc_descriptor 

261 return self 

262  

263 @property 

264 def is_ipc_enabled(self) -> bool: 

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

266 Event_check_open(self) 1pijeafbgchdktIlmn

267 return get_event_ipc_enabled(self._h_event) 1pijeafbgchdkIlmn

268  

269 @property 

270 def is_timing_enabled(self) -> bool: 

271 """Return True if the event records timing data, otherwise False.""" 

272 Event_check_open(self) 1wpxeafbgchdtov

273 return get_event_timing_enabled(self._h_event) 1wpxeafbgchdov

274  

275 @property 

276 def is_blocking_sync(self) -> bool: 

277 """Return True if the event uses blocking synchronization (the CPU 

278 thread blocks on :meth:`sync` instead of busy-waiting), otherwise False. 

279 """ 

280 Event_check_open(self) 1wpxeafbgchdt%

281 return get_event_is_blocking_sync(self._h_event) 1wpxeafbgchd%

282  

283 def sync(self) -> None: 

284 """Synchronize until the event completes. 

285  

286 If the event was created with ``blocking_sync=True``, the 

287 calling CPU thread blocks (yields) until the event has been 

288 completed by the device. Otherwise (the default) the CPU 

289 thread busy-waits until the event has completed. 

290  

291 """ 

292 Event_check_open(self) 1tuBFyG

293 with nogil: 1uBFyG

294 HANDLE_RETURN(cydriver.cuEventSynchronize(as_cu(self._h_event))) 1uBFyG

295  

296 @property 

297 def is_done(self) -> bool: 

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

299 Event_check_open(self) 1wzAqrstB#F

300 with nogil: 1wzAqrsB#F

301 result = cydriver.cuEventQuery(as_cu(self._h_event)) 1wzAqrsB#F

302 if result == cydriver.CUresult.CUDA_SUCCESS: 1wzAqrsB#F

303 return True 1wzAqrs#F

304 if result == cydriver.CUresult.CUDA_ERROR_NOT_READY: 1qrsB

305 return False 1qrsB

306 HANDLE_RETURN(result) 

307  

308 @property 

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

310 """Return the underlying CUevent object. 

311  

312 .. caution:: 

313  

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

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

316 """ 

317 return as_py(self._h_event) 2i j / udrd

318  

319 @property 

320 def device(self) -> Device: 

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

322  

323 Note 

324 ---- 

325 The current context on the device may differ from this 

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

327 context is set current after a event is created. 

328  

329 """ 

330 Event_check_open(self) 1pxt!

331 cdef int dev_id = get_event_device_id(self._h_event) 1px!

332 if dev_id >= 0: 1px!

333 from ._device import Device # avoid circular import 1px!

334 return Device(dev_id) 1px!

335  

336 @property 

337 def context(self) -> Context: 

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

339 Event_check_open(self) 1t9G

340 cdef ContextHandle h_ctx = get_event_context(self._h_event) 19G

341 cdef int dev_id = get_event_device_id(self._h_event) 19G

342 if h_ctx and dev_id >= 0: 19G

343 return Context._from_handle(Context, h_ctx, dev_id) 19G

344  

345cdef Event Event_accept(object arg): 

346 if not isinstance(arg, Event): 1JKLMNOPQRSTUVWXYZ012345678ktouvy'

347 raise TypeError(f"Event expected, got {type(arg).__name__}") 

348 cdef Event event = <Event>arg 1JKLMNOPQRSTUVWXYZ012345678ktouvy'

349 Event_check_open(event) 1JKLMNOPQRSTUVWXYZ012345678ktouvy'

350 return event 1JKLMNOPQRSTUVWXYZ012345678kouvy'

351  

352  

353cdef class IPCEventDescriptor: 

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

355  

356 cdef: 

357 bytes _reserved 

358 bint _is_blocking_sync 

359  

360 def __init__(self, *arg, **kwargs) -> None: 

361 raise RuntimeError("IPCEventDescriptor objects cannot be instantiated directly. Please use Event APIs.") 2?d

362  

363 @staticmethod 

364 def _init(reserved: bytes, is_blocking_sync: cython.bint) -> IPCEventDescriptor: 

365 cdef IPCEventDescriptor self = IPCEventDescriptor.__new__(IPCEventDescriptor) 2i j e a f b g c h d k fdkdldmdndodpdqdl sdm tdn

366 self._reserved = reserved 2i j e a f b g c h d k fdkdldmdndodpdqdl sdm tdn

367 self._is_blocking_sync = is_blocking_sync 2i j e a f b g c h d k fdkdldmdndodpdqdl sdm tdn

368 return self 2i j e a f b g c h d k fdkdldmdndodpdqdl sdm tdn

369  

370 def __eq__(self, other: object) -> bool: 

371 if not isinstance(other, IPCEventDescriptor): 2e a f b g c h d kdldmdndodpdqd

372 return NotImplemented 2kdldmdndodpd

373 # No need to check self._is_blocking_sync. 

374 return self._reserved == (<IPCEventDescriptor>other)._reserved 2e a f b g c h d qd

375  

376 def __reduce__(self) -> tuple[object, ...]: 

377 return IPCEventDescriptor._init, (self._reserved, self._is_blocking_sync) 2i j e a f b g c h d sdtd

378  

379  

380def _reduce_event(event: Event) -> tuple[object, ...]: 

381 check_multiprocessing_start_method() 1ijeafbgchdl

382 return event.from_ipc_descriptor, (event.ipc_descriptor,) 1ijeafbgchdl

383  

384multiprocessing.reduction.register(Event, _reduce_event)