@@ -98,6 +98,9 @@ struct DataDepsAliasingState
98
98
ainfos_readers:: Dict{AbstractAliasing,Vector{Pair{DTask,Int}}}
99
99
ainfos_overlaps:: Dict{AbstractAliasing,Set{AbstractAliasing}}
100
100
101
+ # Cache ainfo lookups
102
+ ainfo_cache:: Dict{Tuple{Any,Any},AbstractAliasing}
103
+
101
104
function DataDepsAliasingState ()
102
105
data_origin = Dict {AbstractAliasing,MemorySpace} ()
103
106
data_locality = Dict {AbstractAliasing,MemorySpace} ()
@@ -106,8 +109,11 @@ struct DataDepsAliasingState
106
109
ainfos_readers = Dict {AbstractAliasing,Vector{Pair{DTask,Int}}} ()
107
110
ainfos_overlaps = Dict {AbstractAliasing,Set{AbstractAliasing}} ()
108
111
112
+ ainfo_cache = Dict {Tuple{Any,Any},AbstractAliasing} ()
113
+
109
114
return new (data_origin, data_locality,
110
- ainfos_owner, ainfos_readers, ainfos_overlaps)
115
+ ainfos_owner, ainfos_readers, ainfos_overlaps,
116
+ ainfo_cache)
111
117
end
112
118
end
113
119
struct DataDepsNonAliasingState
@@ -156,6 +162,12 @@ struct DataDepsState{State<:Union{DataDepsAliasingState,DataDepsNonAliasingState
156
162
end
157
163
end
158
164
165
+ function aliasing (astate:: DataDepsAliasingState , arg, dep_mod)
166
+ return get! (astate. ainfo_cache, (arg, dep_mod)) do
167
+ return aliasing (arg, dep_mod)
168
+ end
169
+ end
170
+
159
171
# Determine which arguments could be written to, and thus need tracking
160
172
161
173
" Whether `arg` has any writedep in this datadeps region."
@@ -190,7 +202,7 @@ function has_writedep(state::DataDepsState, arg, deps, task::DTask)
190
202
for (readdep, writedep, other_ainfo, _, _) in other_taskdeps
191
203
writedep || continue
192
204
for (dep_mod, _, _) in deps
193
- ainfo = aliasing (arg, dep_mod)
205
+ ainfo = aliasing (state . alias_state, arg, dep_mod)
194
206
if will_alias (ainfo, other_ainfo)
195
207
return true
196
208
end
@@ -221,7 +233,7 @@ function is_writedep(arg, deps, task::DTask)
221
233
end
222
234
223
235
# Aliasing state setup
224
- function populate_task_info! (state:: DataDepsState , spec, task)
236
+ function populate_task_info! (state:: DataDepsState , spec:: DTaskSpec , task:: DTask )
225
237
# Populate task dependencies
226
238
dependencies_to_add = Vector {Tuple{Bool,Bool,AbstractAliasing,<:Any,<:Any}} ()
227
239
@@ -233,13 +245,13 @@ function populate_task_info!(state::DataDepsState, spec, task)
233
245
# Unwrap the Chunk underlying any DTask arguments
234
246
arg = arg isa DTask ? fetch (arg; raw= true ) : arg
235
247
236
- # Skip non-mutable arguments
237
- Base . datatype_pointerfree (typeof (arg)) && continue
248
+ # Skip non-aliasing arguments
249
+ type_may_alias (typeof (arg)) || continue
238
250
239
251
# Add all aliasing dependencies
240
252
for (dep_mod, readdep, writedep) in deps
241
253
if state. aliasing
242
- ainfo = aliasing (arg, dep_mod)
254
+ ainfo = aliasing (state . alias_state, arg, dep_mod)
243
255
else
244
256
ainfo = UnknownAliasing ()
245
257
end
@@ -251,15 +263,16 @@ function populate_task_info!(state::DataDepsState, spec, task)
251
263
end
252
264
253
265
# Track the task result too
254
- push! (dependencies_to_add, (true , true , UnknownAliasing (), identity, task))
266
+ # N.B. We state no readdep/writedep because, while we can't model the aliasing info for the task result yet, we don't want to synchronize because of this
267
+ push! (dependencies_to_add, (false , false , UnknownAliasing (), identity, task))
255
268
256
269
# Record argument/result dependencies
257
270
push! (state. dependencies, task => dependencies_to_add)
258
271
end
259
272
function populate_argument_info! (state:: DataDepsState{DataDepsAliasingState} , arg, deps)
260
273
astate = state. alias_state
261
274
for (dep_mod, readdep, writedep) in deps
262
- ainfo = aliasing (arg, dep_mod)
275
+ ainfo = aliasing (astate, arg, dep_mod)
263
276
264
277
# Initialize owner and readers
265
278
if ! haskey (astate. ainfos_owner, ainfo)
@@ -405,7 +418,7 @@ function generate_slot!(state::DataDepsState, dest_space, data)
405
418
data_converted = move (from_proc, to_proc, data)
406
419
data_chunk = tochunk (data_converted, to_proc)
407
420
@assert processor (data_chunk) in processors (dest_space)
408
- @assert memory_space (data_chunk ) == memory_space (data_converted)
421
+ @assert memory_space (data_converted ) == memory_space (data_chunk) " space mismatch! $( memory_space ( data_converted)) != $( memory_space (data_chunk)) ( $( typeof (data_converted)) vs. $( typeof (data_chunk)) ), spaces ( $orig_space -> $dest_space ) "
409
422
@assert orig_space != memory_space (data_chunk) " space preserved! $orig_space != $(memory_space (data_chunk)) ($(typeof (data)) vs. $(typeof (data_chunk)) ), spaces ($orig_space -> $dest_space )"
410
423
return data_chunk
411
424
end
@@ -664,7 +677,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
664
677
# Is the data written previously or now?
665
678
arg, deps = unwrap_inout (arg)
666
679
arg = arg isa DTask ? fetch (arg; raw= true ) : arg
667
- if Base . datatype_pointerfree (typeof (arg)) || ! has_writedep (state, arg, deps, task)
680
+ if ! type_may_alias (typeof (arg)) || ! has_writedep (state, arg, deps, task)
668
681
@dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ] Skipped copy-to (unwritten)"
669
682
spec. args[idx] = pos => arg
670
683
continue
@@ -676,7 +689,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
676
689
end
677
690
if queue. aliasing
678
691
for (dep_mod, _, _) in deps
679
- ainfo = aliasing (arg, dep_mod)
692
+ ainfo = aliasing (astate, arg, dep_mod)
680
693
data_space = astate. data_locality[ainfo]
681
694
nonlocal = our_space != data_space
682
695
if nonlocal
@@ -736,10 +749,10 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
736
749
for (idx, (_, arg)) in enumerate (task_args)
737
750
arg, deps = unwrap_inout (arg)
738
751
arg = arg isa DTask ? fetch (arg; raw= true ) : arg
739
- Base . datatype_pointerfree (typeof (arg)) && continue
752
+ type_may_alias (typeof (arg)) || continue
740
753
if queue. aliasing
741
754
for (dep_mod, _, writedep) in deps
742
- ainfo = aliasing (arg, dep_mod)
755
+ ainfo = aliasing (astate, arg, dep_mod)
743
756
if writedep
744
757
@dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ][$dep_mod ] Syncing as writer"
745
758
get_write_deps! (state, ainfo, task, write_num, syncdeps)
@@ -769,10 +782,10 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
769
782
for (idx, (_, arg)) in enumerate (task_args)
770
783
arg, deps = unwrap_inout (arg)
771
784
arg = arg isa DTask ? fetch (arg; raw= true ) : arg
772
- Base . datatype_pointerfree (typeof (arg)) && continue
785
+ type_may_alias (typeof (arg)) || continue
773
786
if queue. aliasing
774
787
for (dep_mod, _, writedep) in deps
775
- ainfo = aliasing (arg, dep_mod)
788
+ ainfo = aliasing (astate, arg, dep_mod)
776
789
if writedep
777
790
@dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ][$dep_mod ] Set as owner"
778
791
add_writer! (state, ainfo, task, write_num)
@@ -864,7 +877,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
864
877
for arg in keys (astate. data_origin)
865
878
# Is the data previously written?
866
879
arg, deps = unwrap_inout (arg)
867
- if Base . datatype_pointerfree (typeof (arg)) || ! has_writedep (state, arg, deps)
880
+ if ! type_may_alias (typeof (arg)) || ! has_writedep (state, arg, deps)
868
881
@dagdebug nothing :spawn_datadeps " Skipped copy-from (unwritten)"
869
882
end
870
883
@@ -935,7 +948,7 @@ function spawn_datadeps(f::Base.Callable; static::Bool=true,
935
948
throw (ArgumentError (" Dynamic scheduling is no longer available" ))
936
949
end
937
950
wait_all (; check_errors= true ) do
938
- scheduler = something (scheduler, DATADEPS_SCHEDULER[], :naive ):: Symbol
951
+ scheduler = something (scheduler, DATADEPS_SCHEDULER[], :roundrobin ):: Symbol
939
952
launch_wait = something (launch_wait, DATADEPS_LAUNCH_WAIT[], false ):: Bool
940
953
if launch_wait
941
954
result = spawn_bulk () do
0 commit comments