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
« 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
5from __future__ import annotations
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)
26from cuda.core._utils.cuda_utils cimport (
27 check_or_create_options,
28 HANDLE_RETURN
29)
31import cython
32from dataclasses import dataclass
33import multiprocessing
35from cuda.core._utils.cuda_utils import (
36 CUDAError,
37 check_multiprocessing_start_method,
38)
41@dataclass
42cdef class EventOptions:
43 """Customizable :obj:`~_event.Event` options.
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)
59 """
61 enable_timing: bool | None = False
62 busy_waited_sync: bool | None = False
63 ipc_enabled: bool | None = False
66cdef class Event:
67 """Represent a record at a specific point of execution within a CUDA stream.
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.
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:
78 .. code-block:: python
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")
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.
93 """
95 def __init__(self, *args, **kwargs):
96 raise RuntimeError("Event objects cannot be instantiated directly. Please use Stream APIs (record).") 2?c
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
131 @staticmethod
132 cdef Event _from_handle(EventHandle h_event):
133 """Create an Event wrapping an existing EventHandle.
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
143 cpdef close(self):
144 """Destroy the event.
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
151 def __isub__(self, other):
152 return NotImplemented
154 def __rsub__(self, other):
155 return NotImplemented
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
186 def __hash__(self) -> int:
187 return hash(as_intptr(self._h_event)) 2{ | A } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwbxbybAbBbD E
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
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
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
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
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
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
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
240 def sync(self):
241 """Synchronize until the event completes.
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.
249 """
250 with nogil: 1uwC
251 HANDLE_RETURN(cydriver.cuEventSynchronize(as_cu(self._h_event))) 1uwC
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)
264 @property
265 def handle(self) -> cuda.bindings.driver.CUevent:
266 """Return the underlying CUevent object.
268 .. caution::
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
275 @property
276 def device(self) -> Device:
277 """Return the :obj:`~_device.Device` singleton associated with this event.
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.
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
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
300cdef class IPCEventDescriptor:
301 """Serializable object describing an event that can be shared between processes."""
303 cdef:
304 bytes _reserved
305 bint _busy_waited
307 def __init__(self, *arg, **kwargs):
308 raise RuntimeError("IPCEventDescriptor objects cannot be instantiated directly. Please use Event APIs.")
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
317 def __eq__(self, IPCEventDescriptor rhs):
318 # No need to check self._busy_waited.
319 return self._reserved == rhs._reserved 1eafbgchd
321 def __reduce__(self):
322 return IPCEventDescriptor._init, (self._reserved, self._busy_waited) 1ijeafbgchdlm
325def _reduce_event(event):
326 check_multiprocessing_start_method() 1ijeafbgchdk
327 return event.from_ipc_descriptor, (event.get_ipc_descriptor(),) 1ijeafbgchdk
329multiprocessing.reduction.register(Event, _reduce_event)