1+ module DaggerExt
2+ import Dagger
3+ import DiskArrayEngine: DaggerRunner, create_outars, plan_to_loopranges, generate_outbuffers, generate_inbuffers, merge_outbuffer_collection,
4+ run_loop, read_range, extract_outbuffer, run_block, put_buffer, clean_aggregator, merge_all_outbuffers, flush_all_outbuffers,
5+ get_procgroups, DiskEngineScheduler, run_group, subset_loopranges, callback_and_runfilters
6+ import Distributed: myid, Distributed
7+
8+ make_outbuffer_shard (op,runnerloopranges,workerthreads) = Dagger. shard (per_thread= workerthreads) do
9+ generate_outbuffers (op. outspecs,op. f,runnerloopranges)
10+ end
11+ function DaggerRunner (op,exec_plan,outars= create_outars (op,exec_plan;par_only= true );
12+ workerthreads= false ,threaded= true ,showprogress= true ,restartfile= nothing ,restartmode= :continue )
13+ inars = op. inars
14+ loopranges = plan_to_loopranges (exec_plan)
15+ inbuffers = Dagger. shard (per_thread= workerthreads) do
16+ generate_inbuffers (inars, loopranges)
17+ end
18+ try
19+ generate_outbuffers (op. outspecs,op. f, loopranges)
20+ catch e
21+ rethrow (e)
22+ end
23+ cb, runfilter = callback_and_runfilters (loopranges, showprogress, restartfile, restartmode)
24+ cbc = if ! isempty (cb)
25+ channel = Distributed. RemoteChannel (() -> Channel {Union{Nothing,eltype(loopranges)}} (), 1 )
26+ @async while true
27+ update = take! (channel)
28+ isnothing (update) && break
29+ notify_callback (cb, update)
30+ end
31+ channel
32+ else
33+ ()
34+ end
35+ DaggerRunner (op,loopranges,outars, threaded, workerthreads, inbuffers, cbc, runfilter)
36+ end
37+
38+ buffer_mergefunc (red,:: Type{<:Union{Dagger.Chunk,Dagger.Thunk, Dagger.EagerThunk}} ) = (buf1,buf2) -> begin
39+ @debug " Creating Dagger merge function"
40+ @debug " Fetching x"
41+ fx = fetch (buf1)
42+ @debug " Fetching y"
43+ fy = fetch (buf2)
44+ @debug " Calling function"
45+ merge_outbuffer_collection .(fx,fy,(red,))
46+ end
47+
48+ function run_loop (runner:: DaggerRunner ,loopranges,outbuffers... ;groupspecs= nothing )
49+ @noinline run_loop (runner,runner. op,runner. inbuffers_pure,runner. loopranges,runner. workerthreads,
50+ runner. outars,runner. threaded,loopranges,runner. cbc,runner. runfilter,outbuffers... ;groupspecs)
51+ end
52+
53+
54+ function run_loop (:: DaggerRunner ,op,inbuffers_pure,runnerloopranges,workerthreads,
55+ outars,threaded, loopranges,cbc,runfilter,outbuffers... ;groupspecs= nothing )
56+ @debug " Groupspecs are " , groupspecs
57+ piddir = if groupspecs != = nothing && any (i-> in (:output_chunk ,i. reasons),groupspecs)
58+ tempname ()
59+ else
60+ nothing
61+ end
62+ @debug " Pidddir is $piddir "
63+ local_outbuffers = make_outbuffer_shard (op,runnerloopranges,workerthreads)
64+ op = op
65+ r = broadcast (loopranges) do inow
66+ Dagger. spawn (inbuffers_pure,local_outbuffers,inow,piddir,outars,cbc,runfilter) do inbuffers_pure, outbuffers, inow, piddir, outars,cbc,runfilter
67+ # default_loopbody(inow, op, inbuffers_pure, outbuffers, threaded, outars, cbc, runfilter, piddir)
68+ @debug myid (), " Starting block " , inow
69+ inbuffers_wrapped = read_range .((inow,),op. inars,inbuffers_pure);
70+ outbuffers_now = extract_outbuffer .((inow,),op. outspecs,op. f. init,op. f. buftype,outbuffers)
71+ run_block (op,inow,inbuffers_wrapped,outbuffers_now,threaded)
72+ @debug myid (), " Finished running block " , inow
73+ put_buffer .((inow,),outbuffers_now, outars, (piddir,))
74+ clean_aggregator .(outbuffers)
75+ true
76+ end
77+ end
78+ all (fetch .(r)) || error (" Some workers errored" )
79+ @debug myid (), " Fetched everything"
80+ if (groupspecs != = nothing ) && any (i-> in (:reducedim ,i. reasons),groupspecs)
81+ @debug " Merging buffers"
82+ procs = unique (Dagger. processor .(fetch .(r,raw= true )))
83+ @debug " Affected processors are $procs "
84+ buffers_used = collect (v for (k,v) in local_outbuffers. chunks if any (p-> matches_proc (k,p),procs))
85+ @debug " Merging buffers from $(length (buffers_used)) workers."
86+ buffers_used = fetch .(buffers_used)
87+ collections_merged = merge_all_outbuffers (buffers_used,op. f. red)
88+ @debug " Writing merged buffers $(typeof (collections_merged)) "
89+ unflushed_buffers = Dagger. spawn (collections_merged,outars,piddir) do cm,outars,pdir
90+ flush_all_outbuffers (cm,outars,pdir)
91+ end
92+ if ! isempty (outbuffers)
93+ outbuffers = last (outbuffers)
94+ @debug " Putting back flushed buffers"
95+ r = Dagger. spawn (unflushed_buffers,outbuffers,red) do rembuf,outbuf, red
96+ foreach (rembuf,outbuf) do r,o
97+ if ! isempty (r. buffers)
98+ @debug " Putting back unflushed data"
99+ newagg = merge_outbuffer_collection (o,r,red)
100+ empty! (o)
101+ for k in keys (newagg)
102+ o[k] = newagg
103+ end
104+ end
105+ end
106+ end
107+ fetch (r)
108+ else
109+ @debug " Outbuffers are empty"
110+ return fetch (unflushed_buffers)
111+ @debug " Fetched unflushed buffers"
112+ end
113+ end
114+ GC. gc ()
115+ true
116+ end
117+
118+ matches_proc (k:: Dagger.ThreadProc ,c:: Dagger.ThreadProc ) = k== c
119+ matches_proc (k:: Dagger.OSProc ,c:: Dagger.ThreadProc ) = c. tid != 1 ? error (" Processing was not on tid 1" ) : c. owner == k. pid
120+
121+ function Base. run (runner:: DaggerRunner )
122+ @debug " Starting to run"
123+ groups = get_procgroups (runner. op, runner. loopranges, fetch .(runner. outars))
124+ sch = DiskEngineScheduler (groups, runner. loopranges, runner)
125+ opts = runner. workerthreads ? (;) : (;scope = Dagger. scope (thread= 1 ))
126+ Dagger. with_options (;opts... ) do
127+ @debug " Calling first run_group"
128+ run_group (sch,nothing )
129+ end
130+ runner. outars
131+ end
132+
133+ function schedule (sch:: DiskEngineScheduler ,r:: DaggerRunner ,loopdims,loopsub,groupspecs)
134+ @debug " Starting to schedule: "
135+ r = map (loopsub) do i
136+ lrsub = subset_loopranges (sch. loopranges,loopdims,i. I)
137+ @debug " New split loopranges are: " , lrsub. members
138+ schsub = DiskEngineScheduler (sch. groups,lrsub,sch. runner)
139+ @debug " Spawning"
140+ outbuffers = make_outbuffer_shard (r. op,r. loopranges,r. workerthreads)
141+ Dagger. spawn (schsub,groupspecs,outbuffers) do sched, gs, ob
142+ run_group (sched,gs,ob)
143+ end
144+ end
145+ wait .(r)
146+ end
147+ end
0 commit comments