Peano
Loading...
Searching...
No Matches
blocked_rangeNd.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2017-2021 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifndef __TBB_blocked_rangeNd_H
18#define __TBB_blocked_rangeNd_H
19
20#include <algorithm> // std::any_of
21#include <vector>
22#include <cstddef>
23#include <type_traits> // std::is_same, std::enable_if
24
25#include <oneapi/tbb/detail/_config.h>
26#include <oneapi/tbb/detail/_namespace_injection.h>
27#include <oneapi/tbb/detail/_range_common.h>
28#include <oneapi/tbb/detail/_template_helpers.h>
29
30#include <oneapi/tbb/blocked_range.h>
31
32namespace tbb {
33namespace detail {
34namespace d1 {
35
36/*
37 The blocked_rangeNd_impl uses make_index_sequence<N> to automatically generate a ctor with
38 exactly N arguments of the type tbb::blocked_range<Value>. Such ctor provides an opportunity
39 to use braced-init-list parameters to initialize each dimension.
40 Use of parameters, whose representation is a braced-init-list, but they're not
41 std::initializer_list or a reference to one, produces a non-deduced context
42 within template argument deduction.
43
44 NOTE: blocked_rangeNd must be exactly a templated alias to the blocked_rangeNd_impl
45 (and not e.g. a derived class), otherwise it would need to declare its own ctor
46 facing the same problem that the impl class solves.
47*/
48
49#ifdef TBB_OLD_BLOCKED_RANGE_ND
50
51template<typename Value, unsigned int N, typename = detail::make_index_sequence<N>>
52 __TBB_requires(blocked_range_value<Value>)
53class blocked_rangeNd_impl;
54
55template<typename Value, unsigned int N, std::size_t... Is>
56 __TBB_requires(blocked_range_value<Value>)
57class blocked_rangeNd_impl<Value, N, detail::index_sequence<Is...>> {
58public:
60 using value_type = Value;
61
62private:
78 using dim_range_type = tbb::blocked_range<Value>;
79
80public:
81 blocked_rangeNd_impl() = delete;
82
103 blocked_rangeNd_impl(
104 //Value begin[N],
105 Value end[N],
106 typename tbb::blocked_range<value_type>::size_type grainsize
107 ):
108 my_dims() {
109 for (int d=0; d<N; d++) {
110 // my_dims.push_back( dim_range_type( begin[d], end[d], grainsize ) );
111 my_dims.push_back( dim_range_type( 0, end[d], grainsize ) );
112 }
113 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
114 }
115
117 static constexpr unsigned int ndims() { return N; }
118
120 const tbb::blocked_range<value_type>& dim(unsigned int dimension) const {
121 __TBB_ASSERT(dimension < N, "out of bound");
122 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
123 return my_dims[dimension];
124 }
125
126 //------------------------------------------------------------------------
127 // Methods that implement Range concept
128 //------------------------------------------------------------------------
129
131 bool empty() const {
132 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
133 return d.empty();
134 });
135 }
136
138 bool is_divisible() const {
139 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
140 return d.is_divisible();
141 });
142 }
143
144 blocked_rangeNd_impl(blocked_rangeNd_impl& r, proportional_split proportion) : my_dims(r.my_dims) {
145 do_split(r, proportion);
146 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
147 }
148
149 blocked_rangeNd_impl(blocked_rangeNd_impl& r, split proportion) : my_dims(r.my_dims) {
150 do_split(r, proportion);
151 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
152 }
153
154private:
155 static_assert(N != 0, "zero dimensional blocked_rangeNd can't be constructed");
156
162 std::vector<tbb::blocked_range<value_type>> my_dims;
163
164 template<typename split_type>
165 void do_split(blocked_rangeNd_impl& r, split_type proportion) {
166 static_assert((std::is_same<split_type, split>::value || std::is_same<split_type, proportional_split>::value), "type of split object is incorrect");
167 __TBB_ASSERT(r.is_divisible(), "can't split not divisible range");
168
169 auto my_it = std::max_element(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& first, const tbb::blocked_range<value_type>& second) {
170 return (first.size() * second.grainsize() < second.size() * first.grainsize());
171 });
172
173 auto r_it = r.my_dims.begin() + (my_it - my_dims.begin());
174
175 my_it->my_begin = tbb::blocked_range<value_type>::do_split(*r_it, proportion);
176
177 // (!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin)) equals to
178 // (my_it->my_begin == r_it->my_end), but we can't use operator== due to Value concept
179 __TBB_ASSERT(!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin),
180 "blocked_range has been split incorrectly");
181 }
182};
183
184template<typename Value, unsigned int N>
185using blocked_nd_range = blocked_rangeNd_impl<Value, N>;
186
187#else
188
189template<typename Value, unsigned int N, typename = detail::make_index_sequence<N>>
190 __TBB_requires(blocked_range_value<Value>)
192
193template<typename Value, unsigned int N, std::size_t... Is>
194 __TBB_requires(blocked_range_value<Value>)
195class blocked_nd_range_impl<Value, N, detail::index_sequence<Is...>> {
196public:
198 using value_type = Value;
199
200private:
216 using dim_range_type = tbb::blocked_range<Value>;
217
218public:
220
242 //Value begin[N],
243 Value end[N],
244 typename tbb::blocked_range<value_type>::size_type grainsize
245 ):
246 my_dims() {
247 for (int d=0; d<N; d++) {
248 // my_dims.push_back( dim_range_type( begin[d], end[d], grainsize ) );
249 my_dims.push_back( dim_range_type( 0, end[d], grainsize ) );
250 }
251 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
252 }
253
255 static constexpr unsigned int ndims() { return N; }
256
258 const tbb::blocked_range<value_type>& dim(unsigned int dimension) const {
259 __TBB_ASSERT(dimension < N, "out of bound");
260 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
261 return my_dims[dimension];
262 }
263
264 //------------------------------------------------------------------------
265 // Methods that implement Range concept
266 //------------------------------------------------------------------------
267
269 bool empty() const {
270 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
271 return d.empty();
272 });
273 }
274
276 bool is_divisible() const {
277 return std::any_of(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& d) {
278 return d.is_divisible();
279 });
280 }
281
282 blocked_nd_range_impl(blocked_nd_range_impl& r, proportional_split proportion) : my_dims(r.my_dims) {
283 do_split(r, proportion);
284 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
285 }
286
288 do_split(r, proportion);
289 __TBB_ASSERT(my_dims.size()==N, "range is not properly initialised" );
290 }
291
292private:
293 static_assert(N != 0, "zero dimensional blocked_nd_range can't be constructed");
294
300 std::vector<tbb::blocked_range<value_type>> my_dims;
301
302 template<typename split_type>
303 void do_split(blocked_nd_range_impl& r, split_type proportion) {
304 static_assert((std::is_same<split_type, split>::value || std::is_same<split_type, proportional_split>::value), "type of split object is incorrect");
305 __TBB_ASSERT(r.is_divisible(), "can't split not divisible range");
306
307 auto my_it = std::max_element(my_dims.begin(), my_dims.end(), [](const tbb::blocked_range<value_type>& first, const tbb::blocked_range<value_type>& second) {
308 return (first.size() * second.grainsize() < second.size() * first.grainsize());
309 });
310
311 auto r_it = r.my_dims.begin() + (my_it - my_dims.begin());
312
313 my_it->my_begin = tbb::blocked_range<value_type>::do_split(*r_it, proportion);
314
315 // (!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin)) equals to
316 // (my_it->my_begin == r_it->my_end), but we can't use operator== due to Value concept
317 __TBB_ASSERT(!(my_it->my_begin < r_it->my_end) && !(r_it->my_end < my_it->my_begin),
318 "blocked_range has been split incorrectly");
319 }
320};
321
322template<typename Value, unsigned int N>
323using blocked_nd_range = blocked_nd_range_impl<Value, N>;
324
325#endif
326} // namespace d1
327} // namespace detail
328
329inline namespace v1 {
331} // namespace v1
332} // namespace tbb
333
334#endif /* __TBB_blocked_rangeNd_H */
blocked_nd_range_impl()=delete
void do_split(blocked_nd_range_impl &r, split_type proportion)
bool is_divisible() const
True if at least one dimension is divisible.
tbb::blocked_range< Value > dim_range_type
Helper type to construct range with N tbb::blocked_range<value_type> objects.
bool empty() const
True if at least one dimension is empty.
const tbb::blocked_range< value_type > & dim(unsigned int dimension) const
Range in certain dimension.
blocked_nd_range_impl< Value, N > blocked_nd_range
static constexpr unsigned int ndims()
Dimensionality of a range.
__TBB_requires(blocked_range_value< Value >) class blocked_nd_range_impl
std::vector< tbb::blocked_range< value_type > > my_dims
I've written an API to IIT, but I'm not currently using.