1 # SPDX-License-Identifier: BSD-3-Clause
2 # Copyright 2018, Intel Corporation
5 from itertools
import combinations
6 from itertools
import permutations
7 from itertools
import islice
8 from itertools
import chain
9 from random
import sample
10 from functools
import partial
11 from reorderexceptions
import NotSupportedOperationException
15 class FullReorderEngine
:
17 self
.test_on_barrier
= True
19 Realizes a full reordering of stores within a given list.
40 def generate_sequence(self
, store_list
):
42 Generates all possible combinations of all possible lengths,
43 based on the operations in the list.
45 :param store_list: The list of stores to be reordered.
46 :type store_list: list of :class:`memoryoperations.Store`
47 :return: Yields all combinations of stores.
50 for length
in range(0, len(store_list
) + 1):
51 for permutation
in permutations(store_list
, length
):
55 class AccumulativeReorderEngine
:
57 self
.test_on_barrier
= True
59 Realizes an accumulative reorder of stores within a given list.
68 def generate_sequence(self
, store_list
):
70 Generates all accumulative lists,
71 based on the operations in the store list.
73 :param store_list: The list of stores to be reordered.
74 :type store_list: list of :class:`memoryoperations.Store`
75 :return: Yields all accumulative combinations of stores.
79 for i
in range(0, len(store_list
) + 1):
80 out_list
= [store_list
[i
] for i
in range(0, i
)]
84 class AccumulativeReverseReorderEngine
:
86 self
.test_on_barrier
= True
88 Realizes an accumulative reorder of stores
89 within a given list in reverse order.
98 def generate_sequence(self
, store_list
):
100 Reverse all elements order and
101 generates all accumulative lists.
103 :param store_list: The list of stores to be reordered.
104 :type store_list: list of :class:`memoryoperations.Store`
105 :return: Yields all accumulative combinations of stores.
108 store_list
= list(reversed(store_list
))
109 for i
in range(len(store_list
) + 1):
110 yield [store_list
[j
] for j
in range(i
)]
113 class SlicePartialReorderEngine
:
115 Generates a slice of the full reordering of stores within a given list.
117 input: (a, b, c), start = 2, stop = None, step = 2
123 def __init__(self
, start
, stop
, step
=1):
125 Initializes the generator with the provided parameters.
127 :param start: Number of preceding elements to be skipped.
128 :param stop: The element at which the slice is to stop.
129 :param step: How many values are skipped between successive calls.
134 self
.test_on_barrier
= True
136 def generate_sequence(self
, store_list
):
138 This generator yields a slice of all possible combinations.
140 The result may be a set of combinations of different lengths,
141 depending on the slice parameters provided at object creation.
143 :param store_list: The list of stores to be reordered.
144 :type store_list: list of :class:`memoryoperations.Store`
145 :return: Yields a slice of all combinations of stores.
148 for sl
in islice(chain(*map(lambda x
: combinations(store_list
, x
),
149 range(0, len(store_list
) + 1))),
150 self
._start
, self
._stop
, self
._step
):
154 class FilterPartialReorderEngine
:
156 Generates a filtered set of the combinations
157 without duplication of stores within a given list.
159 input: (a, b, c), filter = filter_min_elem, kwarg1 = 2
166 input: (a, b, c), filter = filter_max_elem, kwarg1 = 2
176 input: (a, b, c), filter = filter_between_elem, kwarg1 = 2, kwarg2 = 2
182 def __init__(self
, func
, **kwargs
):
184 Initializes the generator with the provided parameters.
186 :param func: The filter function.
187 :param **kwargs: Arguments to the filter function.
190 self
._filter
_kwargs
= kwargs
191 self
.test_on_barrier
= True
194 def filter_min_elem(store_list
, **kwargs
):
196 Filter stores list if number of element is less than kwarg1
198 if (len(store_list
) < kwargs
["kwarg1"]):
203 def filter_max_elem(store_list
, **kwargs
):
205 Filter stores list if number of element is greater than kwarg1.
207 if (len(store_list
) > kwargs
["kwarg1"]):
212 def filter_between_elem(store_list
, **kwargs
):
214 Filter stores list if number of element is
215 greater or equal kwarg1 and less or equal kwarg2.
217 store_len
= len(store_list
)
218 if (store_len
>= kwargs
["kwarg1"] and store_len
<= kwargs
["kwarg2"]):
222 def generate_sequence(self
, store_list
):
224 This generator yields a filtered set of combinations.
226 :param store_list: The list of stores to be reordered.
227 :type store_list: list of :class:`memoryoperations.Store`
228 :return: Yields a filtered set of combinations.
231 filter_fun
= getattr(self
, self
._filter
, None)
233 partial(filter_fun
, **self
._filter
_kwargs
), chain(
234 *map(lambda x
: combinations(store_list
, x
), range(
235 0, len(store_list
) + 1)))):
239 class RandomPartialReorderEngine
:
241 Generates a random sequence of combinations of stores.
243 input: (a, b, c), max_seq = 3
249 def __init__(self
, max_seq
=3):
251 Initializes the generator with the provided parameters.
253 :param max_seq: The number of combinations to be generated.
255 self
.test_on_barrier
= True
256 self
._max
_seq
= max_seq
258 def generate_sequence(self
, store_list
):
260 This generator yields a random sequence of combinations.
261 Number of combinations without replacement has to be limited to
262 1000 because of exponential growth of elements.
264 for 10 element from 80 -> 1646492110120 combinations
265 for 20 element from 80 -> 3.5353161422122E+18 combinations
266 for 40 element from 80 -> 1.0750720873334E+23 combinations
267 :param store_list: The list of stores to be reordered.
268 :type store_list: list of :class:`memoryoperations.Store`
269 :return: Yields a random sequence of combinations.
272 population
= list(chain(*map(
273 lambda x
: islice(combinations(store_list
, x
), 1000),
274 range(0, len(store_list
) + 1))))
275 population_size
= len(population
)
276 for elem
in sample(population
, self
._max
_seq
if self
._max
_seq
<=
277 population_size
else population_size
):
281 class NoReorderEngine
:
283 self
.test_on_barrier
= True
285 A NULL reorder engine.
290 def generate_sequence(self
, store_list
):
292 This generator does not modify the provided store list.
294 :param store_list: The list of stores to be reordered.
295 :type store_list: The list of :class:`memoryoperations.Store`
296 :return: The unmodified list of stores.
302 class NoCheckerEngine
:
304 self
.test_on_barrier
= False
306 A NULL reorder engine.
311 def generate_sequence(self
, store_list
):
313 This generator does not modify the provided store list
314 and does not do the check.
316 :param store_list: The list of stores to be reordered.
317 :type store_list: The list of :class:`memoryoperations.Store`
318 :return: The unmodified list of stores.
324 def get_engine(engine
):
325 if engine
in engines
:
326 reorder_engine
= engines
[engine
]()
328 raise NotSupportedOperationException(
329 "Not supported reorder engine: {}"
332 return reorder_engine
335 engines
= collections
.OrderedDict([
336 ('NoReorderNoCheck', NoCheckerEngine
),
337 ('ReorderFull', FullReorderEngine
),
338 ('NoReorderDoCheck', NoReorderEngine
),
339 ('ReorderAccumulative', AccumulativeReorderEngine
),
340 ('ReorderReverseAccumulative', AccumulativeReverseReorderEngine
),
341 ('ReorderPartial', RandomPartialReorderEngine
)])