66
77from devito .exceptions import CompilationError
88from devito .ir .iet import (
9- AsyncCall , AsyncCallable , BlankLine , BusyWait , Call , Callable , Conditional , DummyExpr ,
10- FindNodes , List , SyncSpot , SyncSpotRegion , Transformer , derive_parameters ,
9+ AsyncCall , AsyncCallable , BlankLine , Block , BusyWait , Call , Callable , Conditional ,
10+ DummyExpr , FindNodes , List , SyncSpot , SyncSpotRegion , Transformer , derive_parameters ,
1111 make_callable
1212)
1313from devito .ir .iet .visitors import LazyVisitor
@@ -54,12 +54,21 @@ def _fuse_tasks(self, iet):
5454 subs1 = {}
5555
5656 for tasks in groups .values ():
57+ subs1 .update ({task .spot : SyncSpot (task .releases ) for task in tasks })
58+
59+ # Unguarded tasks form separate groups and can share one SyncSpot
60+ if tasks [0 ].guard is None :
61+ sync_ops = tuple (op for task in tasks for op in task .sync_ops )
62+ sync_ops += tuple (tasks [- 1 ].releases )
63+ # Blocks preserve the local scope of each task body
64+ body = [Block (body = task .spot .body ) for task in tasks ]
65+ subs1 [tasks [- 1 ].spot ] = SyncSpot (sync_ops , body = body )
66+ continue
67+
5768 spots = [SyncSpot (task .sync_ops ,
5869 body = Conditional (task .guard , task .spot .body ))
5970 for task in tasks ]
60-
6171 insertions [tasks [- 1 ].anchor ].append (SyncSpotRegion (spots ))
62- subs1 .update ({task .spot : SyncSpot (task .releases ) for task in tasks })
6372
6473 if not subs1 :
6574 return iet
@@ -252,7 +261,7 @@ def ordered(sync_spots):
252261
253262class CollectTasks (LazyVisitor ):
254263
255- """Collect and group guarded asynchronous SyncSpots."""
264+ """Collect and group compatible asynchronous SyncSpots."""
256265
257266 def _post_visit (self , ret ):
258267 groups = defaultdict (list )
@@ -269,25 +278,30 @@ def visit_Conditional(self, o, **kwargs):
269278 yield from self ._visit (o .children , ** kwargs )
270279
271280 def visit_SyncSpot (self , o , iteration = None , condition = None , anchor = None ):
272- if iteration is not None and condition is not None :
281+ if iteration is not None :
273282 syncs = as_mapper (o .sync_ops , type )
274283
275284 optypes = set (syncs )
276285 for optype in (PrefetchUpdate , WithLock ):
277286 if optypes != {optype , ReleaseLock }:
278287 continue
279288
280- # Task SyncSpots inherit a guard without an `else` branch from
281- # the originating Cluster
282- assert not condition .else_body
289+ guard = None
290+ if condition is not None :
291+ # Task SyncSpots inherit a guard without an `else` branch
292+ # from the originating Cluster
293+ assert not condition .else_body
294+ guard = condition .condition
283295
284296 sync_ops = syncs [optype ]
285297
286298 gid , = {i .gid for i in sync_ops }
287299 if gid is not None :
288- task = Task (o , condition . condition , anchor or condition ,
300+ task = Task (o , guard , anchor or condition ,
289301 sync_ops , syncs [ReleaseLock ])
290- yield (iteration , gid , optype , anchor is not None ), task
302+ key = (iteration , gid , optype , anchor is not None ,
303+ condition is not None )
304+ yield key , task
291305
292306 break
293307
0 commit comments