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
« 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
5from __future__ import annotations
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)
27from cuda.core._utils.cuda_utils cimport (
28 check_or_create_options,
29 HANDLE_RETURN
30)
32import cython
33from dataclasses import dataclass
34import multiprocessing
35from typing import TYPE_CHECKING
37from cuda.core._utils.cuda_utils import (
38 CUDAError,
39 check_multiprocessing_start_method,
40)
42if TYPE_CHECKING:
43 import cuda.bindings.driver # no-cython-lint
44 from cuda.core._device import Device
46__all__ = ['Event', 'EventOptions']
49@dataclass
50cdef class EventOptions:
51 """Customizable :obj:`~_event.Event` options.
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)
67 """
69 timing_enabled: bool | None = False
70 blocking_sync: bool | None = False
71 ipc_enabled: bool | None = False
74cdef class Event:
75 """Represent a record at a specific point of execution within a CUDA stream.
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.
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:
86 .. code-block:: python
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")
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.
101 """
103 def __init__(self, *args, **kwargs) -> None:
104 raise RuntimeError("Event objects cannot be instantiated directly. Please use Stream APIs (record).") 2Wd
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'
139 @staticmethod
140 cdef Event _from_handle(EventHandle h_event):
141 """Create an Event wrapping an existing EventHandle.
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
152 cpdef close(self):
153 """Destroy the event.
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
160 @property
161 def is_closed(self) -> bool:
162 """Whether this event has been closed."""
163 return self._h_event.get() == NULL 2t ud
165 def __isub__(self, other: object):
166 return NotImplemented 1=
168 def __rsub__(self, other: object):
169 return NotImplemented 1?
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
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
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
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
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
230 @classmethod
231 def from_ipc_descriptor(cls, ipc_descriptor: IPCEventDescriptor) -> Event:
232 """Import an event that was exported from another process.
234 Parameters
235 ----------
236 ipc_descriptor : :obj:`~_memory._ipc.IPCEventDescriptor`
237 The IPC descriptor obtained from :attr:`~Event.ipc_descriptor` in
238 another process.
240 Returns
241 -------
242 :obj:`~_event.Event`
243 A new event backed by the imported IPC handle.
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
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
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
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%
283 def sync(self) -> None:
284 """Synchronize until the event completes.
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.
291 """
292 Event_check_open(self) 1tuBFyG
293 with nogil: 1uBFyG
294 HANDLE_RETURN(cydriver.cuEventSynchronize(as_cu(self._h_event))) 1uBFyG
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)
308 @property
309 def handle(self) -> cuda.bindings.driver.CUevent:
310 """Return the underlying CUevent object.
312 .. caution::
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
319 @property
320 def device(self) -> Device:
321 """Return the :obj:`~_device.Device` singleton associated with this event.
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.
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!
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
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'
353cdef class IPCEventDescriptor:
354 """Serializable object describing an event that can be shared between processes."""
356 cdef:
357 bytes _reserved
358 bint _is_blocking_sync
360 def __init__(self, *arg, **kwargs) -> None:
361 raise RuntimeError("IPCEventDescriptor objects cannot be instantiated directly. Please use Event APIs.") 2?d
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
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
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
380def _reduce_event(event: Event) -> tuple[object, ...]:
381 check_multiprocessing_start_method() 1ijeafbgchdl
382 return event.from_ipc_descriptor, (event.ipc_descriptor,) 1ijeafbgchdl
384multiprocessing.reduction.register(Event, _reduce_event)