@@ -98,6 +98,9 @@ struct DataDepsAliasingState
9898 ainfos_readers:: Dict{AbstractAliasing,Vector{Pair{DTask,Int}}}
9999 ainfos_overlaps:: Dict{AbstractAliasing,Set{AbstractAliasing}}
100100
101+ # Cache ainfo lookups
102+ ainfo_cache:: Dict{Tuple{Any,Any},AbstractAliasing}
103+
101104 function DataDepsAliasingState ()
102105 data_origin = Dict {AbstractAliasing,MemorySpace} ()
103106 data_locality = Dict {AbstractAliasing,MemorySpace} ()
@@ -106,8 +109,11 @@ struct DataDepsAliasingState
106109 ainfos_readers = Dict {AbstractAliasing,Vector{Pair{DTask,Int}}} ()
107110 ainfos_overlaps = Dict {AbstractAliasing,Set{AbstractAliasing}} ()
108111
112+ ainfo_cache = Dict {Tuple{Any,Any},AbstractAliasing} ()
113+
109114 return new (data_origin, data_locality,
110- ainfos_owner, ainfos_readers, ainfos_overlaps)
115+ ainfos_owner, ainfos_readers, ainfos_overlaps,
116+ ainfo_cache)
111117 end
112118end
113119struct DataDepsNonAliasingState
@@ -156,6 +162,12 @@ struct DataDepsState{State<:Union{DataDepsAliasingState,DataDepsNonAliasingState
156162 end
157163end
158164
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+
159171# Determine which arguments could be written to, and thus need tracking
160172
161173" Whether `arg` has any writedep in this datadeps region."
@@ -190,7 +202,7 @@ function has_writedep(state::DataDepsState, arg, deps, task::DTask)
190202 for (readdep, writedep, other_ainfo, _, _) in other_taskdeps
191203 writedep || continue
192204 for (dep_mod, _, _) in deps
193- ainfo = aliasing (arg, dep_mod)
205+ ainfo = aliasing (state . alias_state, arg, dep_mod)
194206 if will_alias (ainfo, other_ainfo)
195207 return true
196208 end
@@ -221,7 +233,7 @@ function is_writedep(arg, deps, task::DTask)
221233end
222234
223235# Aliasing state setup
224- function populate_task_info! (state:: DataDepsState , spec, task)
236+ function populate_task_info! (state:: DataDepsState , spec:: DTaskSpec , task:: DTask )
225237 # Populate task dependencies
226238 dependencies_to_add = Vector {Tuple{Bool,Bool,AbstractAliasing,<:Any,<:Any}} ()
227239
@@ -233,13 +245,13 @@ function populate_task_info!(state::DataDepsState, spec, task)
233245 # Unwrap the Chunk underlying any DTask arguments
234246 arg = arg isa DTask ? fetch (arg; raw= true ) : arg
235247
236- # Skip non-mutable arguments
237- Base . datatype_pointerfree (typeof (arg)) && continue
248+ # Skip non-aliasing arguments
249+ type_may_alias (typeof (arg)) || continue
238250
239251 # Add all aliasing dependencies
240252 for (dep_mod, readdep, writedep) in deps
241253 if state. aliasing
242- ainfo = aliasing (arg, dep_mod)
254+ ainfo = aliasing (state . alias_state, arg, dep_mod)
243255 else
244256 ainfo = UnknownAliasing ()
245257 end
@@ -251,15 +263,16 @@ function populate_task_info!(state::DataDepsState, spec, task)
251263 end
252264
253265 # 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))
255268
256269 # Record argument/result dependencies
257270 push! (state. dependencies, task => dependencies_to_add)
258271end
259272function populate_argument_info! (state:: DataDepsState{DataDepsAliasingState} , arg, deps)
260273 astate = state. alias_state
261274 for (dep_mod, readdep, writedep) in deps
262- ainfo = aliasing (arg, dep_mod)
275+ ainfo = aliasing (astate, arg, dep_mod)
263276
264277 # Initialize owner and readers
265278 if ! haskey (astate. ainfos_owner, ainfo)
@@ -405,7 +418,7 @@ function generate_slot!(state::DataDepsState, dest_space, data)
405418 data_converted = move (from_proc, to_proc, data)
406419 data_chunk = tochunk (data_converted, to_proc)
407420 @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 ) "
409422 @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 )"
410423 return data_chunk
411424 end
@@ -664,7 +677,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
664677 # Is the data written previously or now?
665678 arg, deps = unwrap_inout (arg)
666679 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)
668681 @dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ] Skipped copy-to (unwritten)"
669682 spec. args[idx] = pos => arg
670683 continue
@@ -676,7 +689,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
676689 end
677690 if queue. aliasing
678691 for (dep_mod, _, _) in deps
679- ainfo = aliasing (arg, dep_mod)
692+ ainfo = aliasing (astate, arg, dep_mod)
680693 data_space = astate. data_locality[ainfo]
681694 nonlocal = our_space != data_space
682695 if nonlocal
@@ -736,10 +749,10 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
736749 for (idx, (_, arg)) in enumerate (task_args)
737750 arg, deps = unwrap_inout (arg)
738751 arg = arg isa DTask ? fetch (arg; raw= true ) : arg
739- Base . datatype_pointerfree (typeof (arg)) && continue
752+ type_may_alias (typeof (arg)) || continue
740753 if queue. aliasing
741754 for (dep_mod, _, writedep) in deps
742- ainfo = aliasing (arg, dep_mod)
755+ ainfo = aliasing (astate, arg, dep_mod)
743756 if writedep
744757 @dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ][$dep_mod ] Syncing as writer"
745758 get_write_deps! (state, ainfo, task, write_num, syncdeps)
@@ -769,10 +782,10 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
769782 for (idx, (_, arg)) in enumerate (task_args)
770783 arg, deps = unwrap_inout (arg)
771784 arg = arg isa DTask ? fetch (arg; raw= true ) : arg
772- Base . datatype_pointerfree (typeof (arg)) && continue
785+ type_may_alias (typeof (arg)) || continue
773786 if queue. aliasing
774787 for (dep_mod, _, writedep) in deps
775- ainfo = aliasing (arg, dep_mod)
788+ ainfo = aliasing (astate, arg, dep_mod)
776789 if writedep
777790 @dagdebug nothing :spawn_datadeps " ($(repr (spec. f)) )[$idx ][$dep_mod ] Set as owner"
778791 add_writer! (state, ainfo, task, write_num)
@@ -864,7 +877,7 @@ function distribute_tasks!(queue::DataDepsTaskQueue)
864877 for arg in keys (astate. data_origin)
865878 # Is the data previously written?
866879 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)
868881 @dagdebug nothing :spawn_datadeps " Skipped copy-from (unwritten)"
869882 end
870883
@@ -935,7 +948,7 @@ function spawn_datadeps(f::Base.Callable; static::Bool=true,
935948 throw (ArgumentError (" Dynamic scheduling is no longer available" ))
936949 end
937950 wait_all (; check_errors= true ) do
938- scheduler = something (scheduler, DATADEPS_SCHEDULER[], :naive ):: Symbol
951+ scheduler = something (scheduler, DATADEPS_SCHEDULER[], :roundrobin ):: Symbol
939952 launch_wait = something (launch_wait, DATADEPS_LAUNCH_WAIT[], false ):: Bool
940953 if launch_wait
941954 result = spawn_bulk () do
0 commit comments