Coverage for cuda / core / _stream.pyx: 87.91%
182 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-08 01:07 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-08 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
7from libc.stdint cimport uintptr_t, INT32_MIN
8from libc.stdlib cimport strtol, getenv
10from cuda.bindings cimport cydriver
12from cuda.core._event cimport Event as cyEvent
13from cuda.core._utils.cuda_utils cimport (
14 check_or_create_options,
15 HANDLE_RETURN,
16)
18import cython
19import warnings
20from dataclasses import dataclass
21from typing import Protocol
23from cuda.core._context cimport Context
24from cuda.core._event import Event, EventOptions
25from cuda.core._resource_handles cimport (
26 ContextHandle,
27 EventHandle,
28 StreamHandle,
29 create_context_handle_ref,
30 create_event_handle_noctx,
31 create_stream_handle,
32 create_stream_handle_with_owner,
33 get_current_context,
34 get_legacy_stream,
35 get_per_thread_stream,
36 as_intptr,
37 as_cu,
38 as_py,
39)
41from cuda.core._graph import GraphBuilder
44@dataclass
45cdef class StreamOptions:
46 """Customizable :obj:`~_stream.Stream` options.
48 Attributes
49 ----------
50 nonblocking : bool, optional
51 Stream does not synchronize with the NULL stream. (Default to True)
52 priority : int, optional
53 Stream priority where lower number represents a
54 higher priority. (Default to lowest priority)
56 """
58 nonblocking : cython.bint = True
59 priority: int | None = None
62class IsStreamT(Protocol):
63 def __cuda_stream__(self) -> tuple[int, int]:
64 """
65 For any Python object that is meant to be interpreted as a CUDA stream, the intent
66 can be communicated by implementing this protocol that returns a 2-tuple: The protocol
67 version number (currently ``0``) and the address of ``cudaStream_t``. Both values
68 should be Python `int`.
69 """
70 ...
73cdef class Stream:
74 """Represent a queue of GPU operations that are executed in a specific order.
76 Applications use streams to control the order of execution for
77 GPU work. Work within a single stream are executed sequentially.
78 Whereas work across multiple streams can be further controlled
79 using stream priorities and :obj:`~_event.Event` managements.
81 Advanced users can utilize default streams for enforce complex
82 implicit synchronization behaviors.
84 Directly creating a :obj:`~_stream.Stream` is not supported due to ambiguity.
85 New streams should instead be created through a :obj:`~_device.Device`
86 object, or created directly through using an existing handle
87 using Stream.from_handle().
88 """
89 def __init__(self, *args, **kwargs):
90 raise RuntimeError( 27e
91 "Stream objects cannot be instantiated directly. "
92 "Please use Device APIs (create_stream) or other Stream APIs (from_handle)."
93 )
95 @staticmethod
96 cdef Stream _from_handle(type cls, StreamHandle h_stream):
97 """Create a Stream from an existing StreamHandle (cdef-only factory)."""
98 cdef Stream s = cls.__new__(cls) 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
99 s._h_stream = h_stream 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
100 # _h_context is default-initialized to empty ContextHandle by C++
101 s._device_id = -1 # lazy init'd (invalid sentinel) 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
102 s._nonblocking = -1 # lazy init'd 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
103 s._priority = INT32_MIN # lazy init'd 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
104 return s 2Y Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cLdM MdQb@ J dd/c:cW X
106 @classmethod
107 def _legacy_default(cls):
108 """Return the legacy default stream (supports subclassing)."""
109 return Stream._from_handle(cls, get_legacy_stream()) 2Y Ld
111 @classmethod
112 def _per_thread_default(cls):
113 """Return the per-thread default stream (supports subclassing)."""
114 return Stream._from_handle(cls, get_per_thread_stream()) 2Y Md
116 @classmethod
117 def _init(cls, obj: IsStreamT | None = None, options=None, device_id: int = None,
118 ctx: Context = None):
119 cdef StreamHandle h_stream
120 cdef cydriver.CUstream borrowed
121 cdef ContextHandle h_context
122 cdef Stream self
124 # Extract context handle if provided
125 if ctx is not None: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cM Qb@ J dd/c:cW X
126 h_context = (<Context>ctx)._h_context 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J /c:cW X
128 if obj is not None and options is not None: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cM Qb@ J dd/c:cW X
129 raise ValueError("obj and options cannot be both specified")
130 if obj is not None: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u cd}c~cI Ub-cMb.cM Qb@ J dd/c:cW X
131 # Borrowed stream from foreign object
132 # C++ handle prevents owner from being GC'd until handle is released
133 # Owner is responsible for keeping the stream's context alive
134 borrowed = _handle_from_stream_protocol(obj) 2D G H K L u cdI M J X
135 h_stream = create_stream_handle_with_owner(borrowed, obj) 2D G H K L u cdI M J
136 return Stream._from_handle(cls, h_stream) 2D G H K L u cdI M J
138 cdef StreamOptions opts = check_or_create_options(StreamOptions, options, "Stream options") 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
139 nonblocking = opts.nonblocking 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
140 priority = opts.priority 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
142 cdef unsigned int flags = (cydriver.CUstream_flags.CU_STREAM_NON_BLOCKING if nonblocking 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
143 else cydriver.CUstream_flags.CU_STREAM_DEFAULT)
144 # TODO: we might want to consider memoizing high/low per CUDA context and avoid this call
145 cdef int high, low
146 with nogil: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
147 HANDLE_RETURN(cydriver.cuCtxGetStreamPriorityRange(&high, &low)) 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
148 cdef int prio
149 if priority is not None: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
150 prio = priority 2MbQb
151 if not (low <= prio <= high): 2MbQb
152 raise ValueError(f"{priority=} is out of range {[low, high]}") 2Qb
153 else:
154 prio = high 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-c.cM @ J dd/c:cW X
156 # C++ creates the stream and returns owning handle with context dependency
157 h_stream = create_stream_handle(h_context, flags, prio) 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
158 if not h_stream: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
159 raise RuntimeError("Failed to create CUDA stream")
160 self = Stream._from_handle(cls, h_stream) 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
161 self._nonblocking = int(nonblocking) 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
162 self._priority = prio 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
163 if device_id is not None: 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
164 self._device_id = device_id 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
165 return self 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F N O P Q R S T U 1 JbKbhbibjbkblbmbnbobpbqbrbsbtbub5 6 7 8 9 ! ;c2 V 3 % ' ( ) * + , - . / 4 Xb: YbZb; D 0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb= ? PbG =c?cGb@c[c]c^c_c`c$cyb%c'c(c)c*czb+c{c|cSbTbadbd# LbH ,cK L u }c~cI Ub-cMb.cM Qb@ J dd/c:cW X
167 cpdef close(self):
168 """Destroy the stream.
170 Releases the stream handle. For owned streams, this destroys the
171 underlying CUDA stream. For borrowed streams, this releases the
172 reference and allows the Python owner to be GC'd.
173 """
174 self._h_stream.reset() 2Z $ y Vbw Wbx dbAbBbCbDbEbFb[ ] ^ _ ` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv
176 def __cuda_stream__(self) -> tuple[int, int]:
177 """Return an instance of a __cuda_stream__ protocol."""
178 return (0, as_intptr(self._h_stream)) 1Du
180 def __hash__(self) -> int:
181 return hash(as_intptr(self._h_stream)) 2G =c?cGb@c[c]c^c_c`c{c|cSbTb8eKdH u ~cI UbJ
183 def __eq__(self, other) -> bool:
184 if not isinstance(other, Stream): 2PbG $cyb%c'c(c)c*c+cSbTbKdH ,cK L u I Ub-cM J :c
185 return NotImplemented 2Pb$cyb%c'c(c)c*c:c
186 return as_intptr(self._h_stream) == as_intptr((<Stream>other)._h_stream) 2PbG +cSbTbKdH ,cK L u I Ub-cM J
188 def __repr__(self) -> str:
189 Stream_ensure_ctx(self) 2E F N O P Q R S T U zb
190 return f"<Stream handle={as_intptr(self._h_stream):#x} context={as_intptr(self._h_context):#x}>" 2E F N O P Q R S T U zb
192 @property
193 def handle(self) -> cuda.bindings.driver.CUstream:
194 """Return the underlying ``CUstream`` object.
196 .. caution::
198 This handle is a Python object. To get the memory address of the underlying C
199 handle, call ``int(Stream.handle)``.
200 """
201 return as_py(self._h_stream) 2Z $ y Vbw Wbx 0 dbAbBbCbDbEbFb[ ] ^ _ ` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv ;cRbPbG H K L }cI M J
203 @property
204 def is_nonblocking(self) -> bool:
205 """Return True if this is a nonblocking stream, otherwise False."""
206 cdef unsigned int flags
207 if self._nonblocking == -1: 2Mb.c
208 with nogil:
209 HANDLE_RETURN(cydriver.cuStreamGetFlags(as_cu(self._h_stream), &flags))
210 self._nonblocking = flags & cydriver.CUstream_flags.CU_STREAM_NON_BLOCKING
211 return bool(self._nonblocking) 2Mb.c
213 @property
214 def priority(self) -> int:
215 """Return the stream priority."""
216 cdef int prio
217 if self._priority == INT32_MIN: 2MbQb
218 with nogil:
219 HANDLE_RETURN(cydriver.cuStreamGetPriority(as_cu(self._h_stream), &prio))
220 self._priority = prio
221 return self._priority 2MbQb
223 def sync(self):
224 """Synchronize the stream."""
225 with nogil: 2Z $ y w 0 db[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C 2 3 : ; D edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd= /cW
226 HANDLE_RETURN(cydriver.cuStreamSynchronize(as_cu(self._h_stream))) 2Z $ y w 0 db[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C 2 3 : ; D edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd= /cW
228 def record(self, event: Event = None, options: EventOptions = None) -> Event:
229 """Record an event onto the stream.
231 Creates an Event object (or reuses the given one) by
232 recording on the stream.
234 Parameters
235 ----------
236 event : :obj:`~_event.Event`, optional
237 Optional event object to be reused for recording.
238 options : :obj:`EventOptions`, optional
239 Customizable dataclass for event creation options.
241 Returns
242 -------
243 :obj:`~_event.Event`
244 Newly created event object.
246 """
247 # Create an Event object (or reusing the given one) by recording
248 # on the stream. Event flags such as disabling timing, nonblocking,
249 # and CU_EVENT_RECORD_EXTERNAL, can be set in EventOptions.
250 if event is None: 2w x a b c d e f g h i j k l m n o p q r s t v E F N O P Q R S T U 1 JbKb2 V 3 % ' ( ) * + , - . / 4 ? @ W
251 Stream_ensure_ctx_device(self) 2w x a b c d e f g h i j k l m n o p q r s t v E F N O P Q R S T U 1 JbKb2 V 3 % ' ( ) * + , - . / 4 ? @ W
252 event = cyEvent._init(cyEvent, self._device_id, self._h_context, options, False) 2w x a b c d e f g h i j k l m n o p q r s t v E F N O P Q R S T U 1 JbKb2 V 3 % ' ( ) * + , - . / 4 ? @ W
253 elif event.is_ipc_enabled: 11
254 raise TypeError( 11
255 "IPC-enabled events should not be re-recorded, instead create a "
256 "new event by supplying options."
257 )
259 cdef cydriver.CUevent e = as_cu((<cyEvent?>(event))._h_event) 1wxabcdefghijklmnopqrstvEFNOPQRSTU12V3%'()*+,-./4?@W
260 with nogil: 1wxabcdefghijklmnopqrstvEFNOPQRSTU12V3%'()*+,-./4?@W
261 HANDLE_RETURN(cydriver.cuEventRecord(e, as_cu(self._h_stream))) 1wxabcdefghijklmnopqrstvEFNOPQRSTU12V3%'()*+,-./4?@W
262 return event 1wxabcdefghijklmnopqrstvEFNOPQRSTU12V3%'()*+,-./4?@W
264 def wait(self, event_or_stream: Event | Stream):
265 """Wait for a CUDA event or a CUDA stream.
267 Waiting for an event or a stream establishes a stream order.
269 If a :obj:`~_stream.Stream` is provided, then wait until the stream's
270 work is completed. This is done by recording a new :obj:`~_event.Event`
271 on the stream and then waiting on it.
273 """
274 cdef Stream stream
275 cdef EventHandle h_event
277 # Handle Event directly
278 if isinstance(event_or_stream, Event): 1wxabcdefghijklmnopqrstvWX
279 with nogil: 1wxabcdefghijklmnopqrstvW
280 # TODO: support flags other than 0?
281 HANDLE_RETURN(cydriver.cuStreamWaitEvent( 1wxabcdefghijklmnopqrstvW
282 as_cu(self._h_stream), as_cu((<cyEvent>event_or_stream)._h_event), 0))
283 return 1wxabcdefghijklmnopqrstvW
285 # Convert to Stream if needed
286 if isinstance(event_or_stream, Stream): 1wxabcdefghijklmnopqrstvX
287 stream = <Stream>event_or_stream 1wxabcdefghijklmnopqrstv
288 else:
289 try: 1X
290 stream = Stream._init(obj=event_or_stream) 1X
291 except Exception as e: 1X
292 raise ValueError( 1X
293 "only an Event, Stream, or object supporting __cuda_stream__ can be waited," 1X
294 f" got {type(event_or_stream)}" 1X
295 ) from e 1X
297 # Wait on stream via temporary event
298 with nogil: 1wxabcdefghijklmnopqrstv
299 h_event = create_event_handle_noctx(cydriver.CUevent_flags.CU_EVENT_DISABLE_TIMING) 1wxabcdefghijklmnopqrstv
300 HANDLE_RETURN(cydriver.cuEventRecord(as_cu(h_event), as_cu(stream._h_stream))) 1wxabcdefghijklmnopqrstv
301 # TODO: support flags other than 0?
302 HANDLE_RETURN(cydriver.cuStreamWaitEvent(as_cu(self._h_stream), as_cu(h_event), 0)) 1wxabcdefghijklmnopqrstv
304 @property
305 def device(self) -> Device:
306 """Return the :obj:`~_device.Device` singleton associated with this stream.
308 Note
309 ----
310 The current context on the device may differ from this
311 stream's context. This case occurs when a different CUDA
312 context is set current after a stream is created.
314 """
315 from cuda.core._device import Device # avoid circular import 2y w x a b c d e f g h i j k l m n o p q r s t z A B C v ; Lbu
316 Stream_ensure_ctx_device(self) 2y w x a b c d e f g h i j k l m n o p q r s t z A B C v ; Lbu
317 return Device(self._device_id) 2y w x a b c d e f g h i j k l m n o p q r s t z A B C v ; Lbu
319 @property
320 def context(self) -> Context:
321 """Return the :obj:`~_context.Context` associated with this stream."""
322 Stream_ensure_ctx(self) 1yabcdefghijklmnopqrstzABCv56789!#u
323 Stream_ensure_ctx_device(self) 1yabcdefghijklmnopqrstzABCv56789!#u
324 return Context._from_handle(Context, self._h_context, self._device_id) 1yabcdefghijklmnopqrstzABCv56789!#u
326 @staticmethod
327 def from_handle(handle: int) -> Stream:
328 """Create a new :obj:`~_stream.Stream` object from a foreign stream handle.
330 Uses a cudaStream_t pointer address represented as a Python int
331 to create a new :obj:`~_stream.Stream` object.
333 Note
334 ----
335 Stream lifetime is not managed, foreign object must remain
336 alive while this steam is active.
338 Parameters
339 ----------
340 handle : int
341 Stream handle representing the address of a foreign
342 stream object.
344 Returns
345 -------
346 :obj:`~_stream.Stream`
347 Newly created stream object.
349 """
351 class _stream_holder: 2G H K L cdI M J
352 def __cuda_stream__(self): 2G H K L cdI M J
353 return (0, handle) 2G H K L cdI M J
355 return Stream._init(obj=_stream_holder()) 2G H K L cdI M J
357 def create_graph_builder(self) -> GraphBuilder:
358 """Create a new :obj:`~_graph.GraphBuilder` object.
360 The new graph builder will be associated with this stream.
362 Returns
363 -------
364 :obj:`~_graph.GraphBuilder`
365 Newly created graph builder object.
367 """
368 return GraphBuilder._init(stream=self, is_stream_owner=False) 1$0
371# c-only python objects, not public
372cdef Stream C_LEGACY_DEFAULT_STREAM = Stream._legacy_default()
373cdef Stream C_PER_THREAD_DEFAULT_STREAM = Stream._per_thread_default()
375# standard python objects, public
376LEGACY_DEFAULT_STREAM = C_LEGACY_DEFAULT_STREAM
377PER_THREAD_DEFAULT_STREAM = C_PER_THREAD_DEFAULT_STREAM
380cpdef Stream default_stream():
381 """Return the default CUDA :obj:`~_stream.Stream`.
383 The type of default stream returned depends on if the environment
384 variable CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM is set.
386 If set, returns a per-thread default stream. Otherwise returns
387 the legacy stream.
389 """
390 # TODO: flip the default
391 cdef const char* use_ptds_raw = getenv("CUDA_PYTHON_CUDA_PER_THREAD_DEFAULT_STREAM") 2Z y 0 a b c d e f g h i j k l m n o p q r s t z A B C NdOdPdQdRdSdE F TdUdVdWdXdYdZd0dhbibjbkblbmbnbob1d2d3d4dpbqbrbsbtbub5d6dV : edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd7d8d9d!dvb#dwb$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]dxb^d_d= `d{d|d}d~daebecedeGbeefegeheiejekeyblemeneoepeqereseKdteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e
393 cdef int use_ptds = 0 2Z y 0 a b c d e f g h i j k l m n o p q r s t z A B C NdOdPdQdRdSdE F TdUdVdWdXdYdZd0dhbibjbkblbmbnbob1d2d3d4dpbqbrbsbtbub5d6dV : edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd7d8d9d!dvb#dwb$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]dxb^d_d= `d{d|d}d~daebecedeGbeefegeheiejekeyblemeneoepeqereseKdteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e
394 if use_ptds_raw != NULL: 2Z y 0 a b c d e f g h i j k l m n o p q r s t z A B C NdOdPdQdRdSdE F TdUdVdWdXdYdZd0dhbibjbkblbmbnbob1d2d3d4dpbqbrbsbtbub5d6dV : edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd7d8d9d!dvb#dwb$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]dxb^d_d= `d{d|d}d~daebecedeGbeefegeheiejekeyblemeneoepeqereseKdteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e
395 use_ptds = strtol(use_ptds_raw, NULL, 10)
397 # value is non-zero, including for weird stuff like 123foo
398 if use_ptds: 2Z y 0 a b c d e f g h i j k l m n o p q r s t z A B C NdOdPdQdRdSdE F TdUdVdWdXdYdZd0dhbibjbkblbmbnbob1d2d3d4dpbqbrbsbtbub5d6dV : edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd7d8d9d!dvb#dwb$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]dxb^d_d= `d{d|d}d~daebecedeGbeefegeheiejekeyblemeneoepeqereseKdteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e
399 return C_PER_THREAD_DEFAULT_STREAM
400 else:
401 return C_LEGACY_DEFAULT_STREAM 2Z y 0 a b c d e f g h i j k l m n o p q r s t z A B C NdOdPdQdRdSdE F TdUdVdWdXdYdZd0dhbibjbkblbmbnbob1d2d3d4dpbqbrbsbtbub5d6dV : edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd7d8d9d!dvb#dwb$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]dxb^d_d= `d{d|d}d~daebecedeGbeefegeheiejekeyblemeneoepeqereseKdteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNeOePeQeReSeTeUeVeWeXeYeZe0e1e2e3e4e5e6e
404cdef inline int Stream_ensure_ctx(Stream self) except?-1 nogil:
405 """Ensure the stream's context handle is populated."""
406 cdef cydriver.CUcontext ctx
407 if not self._h_context: 2y a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 5 6 7 8 9 ! zb# u
408 HANDLE_RETURN(cydriver.cuStreamGetCtx(as_cu(self._h_stream), &ctx)) 2y a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 5 6 7 8 9 ! zb# u
409 with gil: 2y a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 5 6 7 8 9 ! zb# u
410 self._h_context = create_context_handle_ref(ctx) 2y a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 5 6 7 8 9 ! zb# u
411 return 0 2y a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 5 6 7 8 9 ! zb# u
414cdef inline int Stream_ensure_ctx_device(Stream self) except?-1:
415 """Ensure the stream's context and device_id are populated."""
416 cdef cydriver.CUcontext ctx
417 cdef cydriver.CUdevice target_dev
418 cdef bint switch_context
420 if self._device_id < 0: 2y w x a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 1 JbKb5 6 7 8 9 ! 2 V 3 % ' ( ) * + , - . / 4 ; ? # Lbu @ W
421 with nogil: 1u
422 # Get device ID from context, switching context temporarily if needed
423 Stream_ensure_ctx(self) 1u
424 switch_context = (get_current_context() != self._h_context) 1u
425 if switch_context: 1u
426 HANDLE_RETURN(cydriver.cuCtxPushCurrent(as_cu(self._h_context))) 1u
427 HANDLE_RETURN(cydriver.cuCtxGetDevice(&target_dev)) 1u
428 if switch_context: 1u
429 HANDLE_RETURN(cydriver.cuCtxPopCurrent(&ctx)) 1u
430 self._device_id = <int>target_dev 1u
431 return 0 2y w x a b c d e f g h i j k l m n o p q r s t z A B C v E F N O P Q R S T U 1 JbKb5 6 7 8 9 ! 2 V 3 % ' ( ) * + , - . / 4 ; ? # Lbu @ W
434cdef cydriver.CUstream _handle_from_stream_protocol(obj) except*:
435 if isinstance(obj, Stream): 2D G H K L u cdI M J X
436 return <cydriver.CUstream><uintptr_t>(obj.handle)
438 try: 2D G H K L u cdI M J X
439 cuda_stream_attr = obj.__cuda_stream__ 2D G H K L u cdI M J X
440 except AttributeError: 1X
441 raise TypeError(f"{type(obj)} object does not have a '__cuda_stream__' attribute") from None 1X
443 if callable(cuda_stream_attr): 2D G H K L u cdI M J
444 info = cuda_stream_attr() 2D G H K L u cdI M J
445 else:
446 info = cuda_stream_attr
447 warnings.simplefilter("once", DeprecationWarning)
448 warnings.warn(
449 "Implementing __cuda_stream__ as an attribute is deprecated; it must be implemented as a method",
450 stacklevel=3,
451 category=DeprecationWarning,
452 )
454 try: 2D G H K L u cdI M J
455 len_info = len(info) 2D G H K L u cdI M J
456 except TypeError as e:
457 raise RuntimeError(f"obj.__cuda_stream__ must return a sequence with 2 elements, got {type(info)}") from e
458 if len_info != 2: 2D G H K L u cdI M J
459 raise RuntimeError(f"obj.__cuda_stream__ must return a sequence with 2 elements, got {len_info} elements")
460 if info[0] != 0: 2D G H K L u cdI M J
461 raise RuntimeError(
462 f"The first element of the sequence returned by obj.__cuda_stream__ must be 0, got {repr(info[0])}"
463 )
464 return <cydriver.CUstream><uintptr_t>(info[1]) 2D G H K L u cdI M J
466# Helper for API functions that accept either Stream or GraphBuilder. Performs
467# needed checks and returns the relevant stream.
468cdef Stream Stream_accept(arg, bint allow_stream_protocol=False):
469 if isinstance(arg, Stream): 2Z $ y w x 0 dbAbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv E F hbibjbkblbmbnbobpbqbrbsbtbubV 4 Xb: YbZb; D edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb=
470 return <Stream>(arg) 2$ AbBbCbDbEbFb[ Nb] ^ _ Ob` { | } ~ abbbcbE F hbibjbkblbmbnbobpbqbrbsbtbubV 4 Xb: YbZb; D edfdgdhdidjdkdldmdndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJd0b1b2b3b4b5b6b7b8b9b!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#cvbwbRbxb=
471 elif isinstance(arg, GraphBuilder): 2Z $ y w x 0 dbAbBbCbDbEbFb[ ] ^ _ ` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv D
472 return <Stream>(arg.stream) 2Z $ y w x 0 dbAbBbCbDbEbFb[ ] ^ _ ` { | } ~ ebfbgbabbbcba b c d e f g h i j k l m n o p q r s t z A B C HbIbv
473 elif allow_stream_protocol and hasattr(arg, "__cuda_stream__"): 1D
474 stream = Stream._init(arg) 1D
475 warnings.warn( 1D
476 "Passing foreign stream objects to this function via the "
477 "stream protocol is deprecated. Convert the object explicitly "
478 "using Stream(obj) instead.",
479 stacklevel=2,
480 category=DeprecationWarning, 1D
481 )
482 return <Stream>(stream) 1D
483 raise TypeError(f"Stream or GraphBuilder expected, got {type(arg).__name__}")