17 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 #include <Kokkos_Macros.hpp>
20 "Including non-public Kokkos header files is not allowed.");
22 #ifndef KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
23 #define KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
25 #include <initializer_list>
28 #include <Kokkos_Rank.hpp>
29 #include <Kokkos_Array.hpp>
30 #include <impl/KokkosExp_Host_IterateTile.hpp>
31 #include <Kokkos_ExecPolicy.hpp>
32 #include <type_traits>
48 template <
typename ExecSpace>
49 struct default_outer_direction {
51 static constexpr Iterate value = Iterate::Right;
54 template <
typename ExecSpace>
55 struct default_inner_direction {
57 static constexpr Iterate value = Iterate::Right;
64 constexpr std::enable_if_t<!std::is_signed_v<T>,
bool>
65 is_less_than_value_initialized_variable(T) {
70 constexpr std::enable_if_t<std::is_signed_v<T>,
bool>
71 is_less_than_value_initialized_variable(T arg) {
76 template <
class To,
class From>
77 constexpr To checked_narrow_cast(From arg, std::size_t idx) {
78 constexpr
const bool is_different_signedness =
79 (std::is_signed_v<To> != std::is_signed_v<From>);
80 auto const ret =
static_cast<To
>(arg);
81 if (static_cast<From>(ret) != arg ||
82 (is_different_signedness &&
83 is_less_than_value_initialized_variable(arg) !=
84 is_less_than_value_initialized_variable(ret))) {
86 "Kokkos::MDRangePolicy bound type error: an unsafe implicit conversion "
87 "is performed on a bound (" +
88 std::to_string(arg) +
") in dimension (" + std::to_string(idx) +
89 "), which may not preserve its original value.\n";
90 Kokkos::abort(msg.c_str());
100 template <
class IndexType,
class Array,
class U, std::
size_t M>
101 constexpr Array to_array_potentially_narrowing(
const U (&init)[M]) {
102 using T =
typename Array::value_type;
104 constexpr std::size_t N = a.size();
105 static_assert(M <= N);
106 auto* ptr = a.data();
111 for (std::size_t i = 0; i < M; ++i) {
112 *ptr++ = checked_narrow_cast<T>(init[i], i);
113 (void)checked_narrow_cast<IndexType>(init[i], i);
122 template <
class IndexType,
class NVCC_WONT_LET_ME_CALL_YOU_Array,
class U,
124 constexpr NVCC_WONT_LET_ME_CALL_YOU_Array to_array_potentially_narrowing(
126 using T =
typename NVCC_WONT_LET_ME_CALL_YOU_Array::value_type;
127 NVCC_WONT_LET_ME_CALL_YOU_Array a{};
128 constexpr std::size_t N = a.size();
129 static_assert(M <= N);
130 for (std::size_t i = 0; i < M; ++i) {
131 a[i] = checked_narrow_cast<T>(other[i], i);
132 (void)checked_narrow_cast<IndexType>(other[i], i);
137 struct TileSizeProperties {
139 int default_largest_tile_size;
140 int default_tile_size;
141 int max_total_tile_size;
144 template <
typename ExecutionSpace>
145 TileSizeProperties get_tile_size_properties(
const ExecutionSpace&) {
147 TileSizeProperties properties;
148 properties.max_threads = std::numeric_limits<int>::max();
149 properties.default_largest_tile_size = 0;
150 properties.default_tile_size = 2;
151 properties.max_total_tile_size = std::numeric_limits<int>::max();
158 template <
typename... Properties>
159 struct MDRangePolicy;
168 template <
typename P,
typename... Properties>
169 struct MDRangePolicy<P, Properties...>
170 :
public Kokkos::Impl::PolicyTraits<P, Properties...> {
171 using traits = Kokkos::Impl::PolicyTraits<P, Properties...>;
172 using range_policy = RangePolicy<P, Properties...>;
174 typename traits::execution_space m_space;
176 using impl_range_policy =
177 RangePolicy<
typename traits::execution_space,
178 typename traits::schedule_type,
typename traits::index_type>;
180 using execution_policy =
181 MDRangePolicy<P, Properties...>;
184 template <
class... OtherProperties>
185 friend struct MDRangePolicy;
187 static_assert(!std::is_void_v<typename traits::iteration_pattern>,
188 "Kokkos Error: MD iteration pattern not defined");
190 using iteration_pattern =
typename traits::iteration_pattern;
191 using work_tag =
typename traits::work_tag;
192 using launch_bounds =
typename traits::launch_bounds;
193 using member_type =
typename range_policy::member_type;
195 static constexpr
int rank = iteration_pattern::rank;
196 static_assert(rank < 7,
"Kokkos MDRangePolicy Error: Unsupported rank...");
198 using index_type =
typename traits::index_type;
199 using array_index_type = std::int64_t;
213 point_type m_lower = {};
214 point_type m_upper = {};
215 tile_type m_tile = {};
216 point_type m_tile_end = {};
217 index_type m_num_tiles = 1;
218 index_type m_prod_tile_dims = 1;
219 bool m_tune_tile_size =
false;
221 static constexpr
auto outer_direction =
222 (iteration_pattern::outer_direction != Iterate::Default)
223 ? iteration_pattern::outer_direction
224 : default_outer_direction<typename traits::execution_space>::value;
226 static constexpr
auto inner_direction =
227 iteration_pattern::inner_direction != Iterate::Default
228 ? iteration_pattern::inner_direction
229 : default_inner_direction<typename traits::execution_space>::value;
231 static constexpr
auto Right = Iterate::Right;
232 static constexpr
auto Left = Iterate::Left;
234 KOKKOS_INLINE_FUNCTION
const typename traits::execution_space& space()
const {
238 MDRangePolicy() =
default;
240 template <
typename LT, std::size_t LN,
typename UT, std::size_t UN,
241 typename TT = array_index_type, std::size_t TN = rank,
242 typename = std::enable_if_t<std::is_integral_v<LT> &&
243 std::is_integral_v<UT> &&
244 std::is_integral_v<TT>>>
245 MDRangePolicy(
const LT (&lower)[LN],
const UT (&upper)[UN],
246 const TT (&tile)[TN] = {})
248 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
250 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
252 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
255 LN == rank && UN == rank && TN <= rank,
256 "MDRangePolicy: Constructor initializer lists have wrong size");
259 template <
typename LT, std::size_t LN,
typename UT, std::size_t UN,
260 typename TT = array_index_type, std::size_t TN = rank,
261 typename = std::enable_if_t<std::is_integral_v<LT> &&
262 std::is_integral_v<UT> &&
263 std::is_integral_v<TT>>>
264 MDRangePolicy(
const typename traits::execution_space& work_space,
265 const LT (&lower)[LN],
const UT (&upper)[UN],
266 const TT (&tile)[TN] = {})
269 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
271 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
273 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
276 LN == rank && UN == rank && TN <= rank,
277 "MDRangePolicy: Constructor initializer lists have wrong size");
283 MDRangePolicy(point_type
const& lower, point_type
const& upper,
284 tile_type
const& tile = tile_type{})
285 : MDRangePolicy(
typename traits::execution_space(), lower, upper, tile) {}
287 MDRangePolicy(
const typename traits::execution_space& work_space,
288 point_type
const& lower, point_type
const& upper,
289 tile_type
const& tile = tile_type{})
290 : m_space(work_space), m_lower(lower), m_upper(upper), m_tile(tile) {
291 init_helper(Impl::get_tile_size_properties(work_space));
294 template <
typename T, std::size_t NT = rank,
295 typename = std::enable_if_t<std::is_integral_v<T>>>
299 : MDRangePolicy(
typename traits::execution_space(), lower, upper, tile) {}
301 template <
typename T, std::size_t NT = rank,
302 typename = std::enable_if_t<std::is_integral_v<T>>>
303 MDRangePolicy(
const typename traits::execution_space& work_space,
309 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
311 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
313 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
316 template <
class... OtherProperties>
317 MDRangePolicy(
const MDRangePolicy<OtherProperties...> p)
323 m_tile_end(p.m_tile_end),
324 m_num_tiles(p.m_num_tiles),
325 m_prod_tile_dims(p.m_prod_tile_dims),
326 m_tune_tile_size(p.m_tune_tile_size) {}
328 void impl_change_tile_size(
const point_type& tile) {
330 init_helper(Impl::get_tile_size_properties(m_space));
332 bool impl_tune_tile_size()
const {
return m_tune_tile_size; }
334 tile_type tile_size_recommended()
const {
335 tile_type rec_tile_sizes = {};
337 for (std::size_t i = 0; i < rec_tile_sizes.size(); ++i) {
338 rec_tile_sizes[i] = tile_size_recommended(i);
340 return rec_tile_sizes;
343 int max_total_tile_size()
const {
344 return Impl::get_tile_size_properties(m_space).max_total_tile_size;
348 int tile_size_recommended(
const int tile_rank)
const {
349 auto properties = Impl::get_tile_size_properties(m_space);
350 int last_rank = (inner_direction == Iterate::Right) ? rank - 1 : 0;
352 (inner_direction == Iterate::Right) ? tile_rank + 1 : tile_rank - 1;
353 int rec_tile_size = (std::pow(properties.default_tile_size, rank_acc) <
354 properties.max_total_tile_size)
355 ? properties.default_tile_size
358 if (tile_rank == last_rank) {
359 rec_tile_size = tile_size_last_rank(
360 properties, m_upper[last_rank] - m_lower[last_rank]);
362 return rec_tile_size;
365 int tile_size_last_rank(
const Impl::TileSizeProperties properties,
366 const index_type length)
const {
367 return properties.default_largest_tile_size == 0
368 ? std::max<int>(length, 1)
369 : properties.default_largest_tile_size;
372 void init_helper(Impl::TileSizeProperties properties) {
373 m_prod_tile_dims = 1;
377 if (inner_direction == Iterate::Right) {
379 rank_start = rank - 1;
383 for (
int i = rank_start; i != rank_end; i += increment) {
384 const index_type length = m_upper[i] - m_lower[i];
386 if (m_upper[i] < m_lower[i]) {
388 "Kokkos::MDRangePolicy bounds error: The lower bound (" +
389 std::to_string(m_lower[i]) +
") is greater than its upper bound (" +
390 std::to_string(m_upper[i]) +
") in dimension " + std::to_string(i) +
392 #if !defined(KOKKOS_ENABLE_DEPRECATED_CODE_4)
393 Kokkos::abort(msg.c_str());
394 #elif defined(KOKKOS_ENABLE_DEPRECATION_WARNINGS)
395 Kokkos::Impl::log_warning(msg);
399 if (m_tile[i] <= 0) {
400 m_tune_tile_size =
true;
401 if ((inner_direction == Iterate::Right && (i < rank - 1)) ||
402 (inner_direction == Iterate::Left && (i > 0))) {
403 if (m_prod_tile_dims * properties.default_tile_size <
404 static_cast<index_type>(properties.max_total_tile_size)) {
405 m_tile[i] = properties.default_tile_size;
410 m_tile[i] = tile_size_last_rank(properties, length);
414 static_cast<index_type
>((length + m_tile[i] - 1) / m_tile[i]);
415 m_num_tiles *= m_tile_end[i];
416 m_prod_tile_dims *= m_tile[i];
418 if (m_prod_tile_dims > static_cast<index_type>(properties.max_threads)) {
419 printf(
" Product of tile dimensions exceed maximum limit: %d\n",
420 static_cast<int>(properties.max_threads));
422 "ExecSpace Error: MDRange tile dims exceed maximum number "
423 "of threads per block - choose smaller tile dims");
428 template <
typename LT,
size_t N,
typename UT>
429 MDRangePolicy(
const LT (&)[N],
const UT (&)[N]) -> MDRangePolicy<Rank<N>>;
431 template <
typename LT,
size_t N,
typename UT,
typename TT,
size_t TN>
432 MDRangePolicy(
const LT (&)[N],
const UT (&)[N],
const TT (&)[TN])
433 -> MDRangePolicy<Rank<N>>;
435 template <
typename LT,
size_t N,
typename UT>
436 MDRangePolicy(DefaultExecutionSpace
const&,
const LT (&)[N],
const UT (&)[N])
437 -> MDRangePolicy<Rank<N>>;
439 template <
typename LT,
size_t N,
typename UT,
typename TT,
size_t TN>
440 MDRangePolicy(DefaultExecutionSpace
const&,
const LT (&)[N],
const UT (&)[N],
441 const TT (&)[TN]) -> MDRangePolicy<Rank<N>>;
443 template <
typename ES,
typename LT,
size_t N,
typename UT,
444 typename = std::enable_if_t<is_execution_space_v<ES>>>
445 MDRangePolicy(ES
const&,
const LT (&)[N],
const UT (&)[N])
446 -> MDRangePolicy<ES, Rank<N>>;
448 template <
typename ES,
typename LT,
size_t N,
typename UT,
typename TT,
449 size_t TN,
typename = std::enable_if_t<is_execution_space_v<ES>>>
450 MDRangePolicy(ES
const&,
const LT (&)[N],
const UT (&)[N],
const TT (&)[TN])
451 -> MDRangePolicy<ES, Rank<N>>;
453 template <
typename T,
size_t N>
454 MDRangePolicy(Array<T, N>
const&, Array<T, N>
const&) -> MDRangePolicy<Rank<N>>;
456 template <
typename T,
size_t N,
size_t NT>
457 MDRangePolicy(Array<T, N>
const&, Array<T, N>
const&, Array<T, NT>
const&)
458 -> MDRangePolicy<Rank<N>>;
460 template <
typename T,
size_t N>
461 MDRangePolicy(DefaultExecutionSpace
const&, Array<T, N>
const&,
462 Array<T, N>
const&) -> MDRangePolicy<Rank<N>>;
464 template <
typename T,
size_t N,
size_t NT>
465 MDRangePolicy(DefaultExecutionSpace
const&, Array<T, N>
const&,
466 Array<T, N>
const&, Array<T, NT>
const&)
467 -> MDRangePolicy<Rank<N>>;
469 template <
typename ES,
typename T,
size_t N,
470 typename = std::enable_if_t<is_execution_space_v<ES>>>
471 MDRangePolicy(ES
const&, Array<T, N>
const&, Array<T, N>
const&)
472 -> MDRangePolicy<ES, Rank<N>>;
474 template <
typename ES,
typename T,
size_t N,
size_t NT,
475 typename = std::enable_if_t<is_execution_space_v<ES>>>
476 MDRangePolicy(ES
const&, Array<T, N>
const&, Array<T, N>
const&,
477 Array<T, NT>
const&) -> MDRangePolicy<ES, Rank<N>>;
481 #endif // KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
Derived from the C++17 'std::array'. Dropping the iterator interface.
Declaration of various MemoryLayout options.