31
31
# - Add a background task that occasionally scans all streams
32
32
# - Add a hysterisis by checking a "since last scanned" timestamp
33
33
const STREAM_GC_LOCK = Threads. ReentrantLock ()
34
+ #=
34
35
function next_stream()
35
36
lock(STREAM_GC_LOCK) do
36
37
if !isempty(FREE_STREAMS)
@@ -53,6 +54,43 @@ function next_stream()
53
54
return stream
54
55
end
55
56
end
57
+ =#
58
+ const FREE_STREAMS_D = Dict {CUDA.CuContext,Array{CUDA.CuStream,1}} ()
59
+ const STREAMS_D = Dict {CUDA.CuContext,Array{CUDA.CuStream,1}} ()
60
+ function next_stream ()
61
+ ctx = CUDA. current_context ()
62
+ lock (STREAM_GC_LOCK) do
63
+ # see if there is a compatible free stream
64
+ FREE_STREAMS_CT = get! (FREE_STREAMS_D, ctx) do
65
+ CUDA. CuStream[]
66
+ end
67
+ if ! isempty (FREE_STREAMS_CT)
68
+ return pop! (FREE_STREAMS_CT)
69
+ end
70
+
71
+ # GC to recover streams that are not busy
72
+ STREAMS_CT = get! (STREAMS_D, ctx) do
73
+ CUDA. CuStream[]
74
+ end
75
+ if length (STREAMS_CT) > STREAM_GC_THRESHOLD[]
76
+ for stream in STREAMS_CT
77
+ if CUDA. query (stream)
78
+ push! (FREE_STREAMS_CT, stream)
79
+ end
80
+ end
81
+ end
82
+
83
+ # if there is a compatible free stream after GC, return that stream
84
+ if ! isempty (FREE_STREAMS_CT)
85
+ return pop! (FREE_STREAMS_CT)
86
+ end
87
+
88
+ # no compatible free stream available so create a new one
89
+ stream = CUDA. CuStream (flags = CUDA. STREAM_NON_BLOCKING)
90
+ push! (STREAMS_CT, stream)
91
+ return stream
92
+ end
93
+ end
56
94
57
95
import KernelAbstractions: Event, CPUEvent, NoneEvent, MultiEvent, CPU, GPU, isdone, failed
58
96
0 commit comments