1- from devito .ir .clusters .cluster import Cluster
2- from devito .ir .clusters .visitors import Queue
1+ from devito .ir .clusters .visitors import QueueStateful
32from devito .ir .support import (AFFINE , PARALLEL , PARALLEL_INDEP , PARALLEL_IF_ATOMIC ,
4- SEQUENTIAL , Property , Scope )
5- from devito .ir .support .space import IterationSpace
3+ SEQUENTIAL )
64from devito .tools import as_tuple , flatten , timed_pass
7- from devito .types .dimension import Dimension
85
96__all__ = ['analyze' ]
107
118
12- # Describes properties fetched by a `Detector`
13- Properties = dict [Cluster , dict [Dimension , set [Property ]]]
14-
15-
169@timed_pass ()
1710def analyze (clusters ):
18- properties : Properties = {}
11+ state = QueueStateful . State ()
1912
2013 # Collect properties
21- clusters = Parallelism ().process (clusters , properties = properties )
22- clusters = Affiness ().process (clusters , properties = properties )
14+ clusters = Parallelism (state ).process (clusters )
15+ clusters = Affiness (state ).process (clusters )
2316
2417 # Reconstruct Clusters attaching the discovered properties
25- processed = [c .rebuild (properties = properties .get (c )) for c in clusters ]
18+ processed = [c .rebuild (properties = state . properties .get (c )) for c in clusters ]
2619
2720 return processed
2821
2922
30- class Detector (Queue ):
23+ class Detector (QueueStateful ):
3124
32- def process (self , clusters : list [ Cluster ], properties : Properties ) -> list [ Cluster ] :
33- return self ._process_fatd (clusters , 1 , properties = properties )
25+ def process (self , elements ) :
26+ return self ._process_fatd (elements , 1 )
3427
35- def callback (self , clusters : list [Cluster ], prefix : IterationSpace | None ,
36- properties : Properties ) -> list [Cluster ]:
28+ def callback (self , clusters , prefix ):
3729 if not prefix :
3830 return clusters
3931
@@ -49,19 +41,11 @@ def callback(self, clusters: list[Cluster], prefix: IterationSpace | None,
4941 # Update `self.state`
5042 if retval :
5143 for c in clusters :
52- c_properties = properties .setdefault (c , {})
53- c_properties .setdefault (d , set ()).update (retval )
44+ properties = self . state . properties .setdefault (c , {})
45+ properties .setdefault (d , set ()).update (retval )
5446
5547 return clusters
5648
57- def _callback (self , clusters : list [Cluster ], dim : Dimension ,
58- prefix : IterationSpace | None ) -> set [Property ]:
59- """
60- Callback to be implemented by subclasses. It should return a set of
61- properties for the given dimension.
62- """
63- raise NotImplementedError ()
64-
6549
6650class Parallelism (Detector ):
6751
@@ -88,27 +72,27 @@ class Parallelism(Detector):
8872 the 'write' is known to be an associative and commutative increment
8973 """
9074
91- def _callback (self , clusters , dim , prefix ):
75+ def _callback (self , clusters , d , prefix ):
9276 # Rule out if non-unitary increment Dimension (e.g., `t0=(time+1)%2`)
93- if any (c .sub_iterators [dim ] for c in clusters ):
94- return { SEQUENTIAL }
77+ if any (c .sub_iterators [d ] for c in clusters ):
78+ return SEQUENTIAL
9579
9680 # All Dimensions up to and including `i-1`
9781 prev = flatten (i .dim ._defines for i in prefix [:- 1 ])
9882
9983 is_parallel_indep = True
10084 is_parallel_atomic = False
10185
102- scope = Scope ( flatten ( c . exprs for c in clusters ) )
86+ scope = self . _fetch_scope ( clusters )
10387 for dep in scope .d_all_gen ():
104- test00 = dep .is_indep (dim ) and not dep .is_storage_related (dim )
88+ test00 = dep .is_indep (d ) and not dep .is_storage_related (d )
10589 test01 = all (dep .is_reduce_atmost (i ) for i in prev )
10690 if test00 and test01 :
10791 continue
10892
10993 test1 = len (prev ) > 0 and any (dep .is_carried (i ) for i in prev )
11094 if test1 :
111- is_parallel_indep &= (dep .distance_mapper .get (dim .root ) == 0 )
95+ is_parallel_indep &= (dep .distance_mapper .get (d .root ) == 0 )
11296 continue
11397
11498 if dep .function in scope .initialized :
@@ -119,14 +103,14 @@ def _callback(self, clusters, dim, prefix):
119103 is_parallel_atomic = True
120104 continue
121105
122- return { SEQUENTIAL }
106+ return SEQUENTIAL
123107
124108 if is_parallel_atomic :
125- return { PARALLEL_IF_ATOMIC }
109+ return PARALLEL_IF_ATOMIC
126110 elif is_parallel_indep :
127111 return {PARALLEL , PARALLEL_INDEP }
128112 else :
129- return { PARALLEL }
113+ return PARALLEL
130114
131115
132116class Affiness (Detector ):
@@ -135,11 +119,8 @@ class Affiness(Detector):
135119 Detect the AFFINE Dimensions.
136120 """
137121
138- def _callback (self , clusters , dim , prefix ):
139- scope = Scope ( flatten ( c . exprs for c in clusters ) )
122+ def _callback (self , clusters , d , prefix ):
123+ scope = self . _fetch_scope ( clusters )
140124 accesses = [a for a in scope .accesses if not a .is_scalar ]
141-
142- if all (a .is_regular and a .affine_if_present (dim ._defines ) for a in accesses ):
143- return {AFFINE }
144-
145- return set ()
125+ if all (a .is_regular and a .affine_if_present (d ._defines ) for a in accesses ):
126+ return AFFINE
0 commit comments