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>
47 template <
typename ExecSpace>
48 struct default_outer_direction {
50 static constexpr Iterate value = Iterate::Right;
53 template <
typename ExecSpace>
54 struct default_inner_direction {
56 static constexpr Iterate value = Iterate::Right;
63 constexpr std::enable_if_t<!std::is_signed<T>::value,
bool>
64 is_less_than_value_initialized_variable(T) {
69 constexpr std::enable_if_t<std::is_signed<T>::value,
bool>
70 is_less_than_value_initialized_variable(T arg) {
75 template <
class To,
class From>
76 constexpr To checked_narrow_cast(From arg, std::size_t idx) {
77 constexpr
const bool is_different_signedness =
78 (std::is_signed<To>::value != std::is_signed<From>::value);
79 auto const ret =
static_cast<To
>(arg);
80 if (static_cast<From>(ret) != arg ||
81 (is_different_signedness &&
82 is_less_than_value_initialized_variable(arg) !=
83 is_less_than_value_initialized_variable(ret))) {
85 "Kokkos::MDRangePolicy bound type error: an unsafe implicit conversion "
86 "is performed on a bound (" +
87 std::to_string(arg) +
") in dimension (" + std::to_string(idx) +
88 "), which may not preserve its original value.\n";
89 Kokkos::abort(msg.c_str());
99 template <
class IndexType,
class Array,
class U, std::
size_t M>
100 constexpr Array to_array_potentially_narrowing(
const U (&init)[M]) {
101 using T =
typename Array::value_type;
103 constexpr std::size_t N = a.size();
104 static_assert(M <= N);
105 auto* ptr = a.data();
110 for (std::size_t i = 0; i < M; ++i) {
111 *ptr++ = checked_narrow_cast<T>(init[i], i);
112 (void)checked_narrow_cast<IndexType>(init[i], i);
121 template <
class IndexType,
class NVCC_WONT_LET_ME_CALL_YOU_Array,
class U,
123 constexpr NVCC_WONT_LET_ME_CALL_YOU_Array to_array_potentially_narrowing(
125 using T =
typename NVCC_WONT_LET_ME_CALL_YOU_Array::value_type;
126 NVCC_WONT_LET_ME_CALL_YOU_Array a{};
127 constexpr std::size_t N = a.size();
128 static_assert(M <= N);
129 for (std::size_t i = 0; i < M; ++i) {
130 a[i] = checked_narrow_cast<T>(other[i], i);
131 (void)checked_narrow_cast<IndexType>(other[i], i);
136 struct TileSizeProperties {
138 int default_largest_tile_size;
139 int default_tile_size;
140 int max_total_tile_size;
143 template <
typename ExecutionSpace>
144 TileSizeProperties get_tile_size_properties(
const ExecutionSpace&) {
146 TileSizeProperties properties;
147 properties.max_threads = std::numeric_limits<int>::max();
148 properties.default_largest_tile_size = 0;
149 properties.default_tile_size = 2;
150 properties.max_total_tile_size = std::numeric_limits<int>::max();
157 template <
typename... Properties>
158 struct MDRangePolicy;
167 template <
typename P,
typename... Properties>
168 struct MDRangePolicy<P, Properties...>
169 :
public Kokkos::Impl::PolicyTraits<P, Properties...> {
170 using traits = Kokkos::Impl::PolicyTraits<P, Properties...>;
171 using range_policy = RangePolicy<P, Properties...>;
173 typename traits::execution_space m_space;
175 using impl_range_policy =
176 RangePolicy<
typename traits::execution_space,
177 typename traits::schedule_type,
typename traits::index_type>;
179 using execution_policy =
180 MDRangePolicy<P, Properties...>;
183 template <
class... OtherProperties>
184 friend struct MDRangePolicy;
186 static_assert(!std::is_void<typename traits::iteration_pattern>::value,
187 "Kokkos Error: MD iteration pattern not defined");
189 using iteration_pattern =
typename traits::iteration_pattern;
190 using work_tag =
typename traits::work_tag;
191 using launch_bounds =
typename traits::launch_bounds;
192 using member_type =
typename range_policy::member_type;
194 static constexpr
int rank = iteration_pattern::rank;
195 static_assert(rank < 7,
"Kokkos MDRangePolicy Error: Unsupported rank...");
197 using index_type =
typename traits::index_type;
198 using array_index_type = std::int64_t;
212 point_type m_lower = {};
213 point_type m_upper = {};
214 tile_type m_tile = {};
215 point_type m_tile_end = {};
216 index_type m_num_tiles = 1;
217 index_type m_prod_tile_dims = 1;
218 bool m_tune_tile_size =
false;
220 static constexpr
auto outer_direction =
221 (iteration_pattern::outer_direction != Iterate::Default)
222 ? iteration_pattern::outer_direction
223 : default_outer_direction<typename traits::execution_space>::value;
225 static constexpr
auto inner_direction =
226 iteration_pattern::inner_direction != Iterate::Default
227 ? iteration_pattern::inner_direction
228 : default_inner_direction<typename traits::execution_space>::value;
230 static constexpr
auto Right = Iterate::Right;
231 static constexpr
auto Left = Iterate::Left;
233 KOKKOS_INLINE_FUNCTION
const typename traits::execution_space& space()
const {
237 MDRangePolicy() =
default;
239 template <
typename LT, std::size_t LN,
typename UT, std::size_t UN,
240 typename TT = array_index_type, std::size_t TN = rank,
241 typename = std::enable_if_t<std::is_integral<LT>::value &&
242 std::is_integral<UT>::value &&
243 std::is_integral<TT>::value>>
244 MDRangePolicy(
const LT (&lower)[LN],
const UT (&upper)[UN],
245 const TT (&tile)[TN] = {})
247 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
249 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
251 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
254 LN == rank && UN == rank && TN <= rank,
255 "MDRangePolicy: Constructor initializer lists have wrong size");
258 template <
typename LT, std::size_t LN,
typename UT, std::size_t UN,
259 typename TT = array_index_type, std::size_t TN = rank,
260 typename = std::enable_if_t<std::is_integral<LT>::value &&
261 std::is_integral<UT>::value &&
262 std::is_integral<TT>::value>>
263 MDRangePolicy(
const typename traits::execution_space& work_space,
264 const LT (&lower)[LN],
const UT (&upper)[UN],
265 const TT (&tile)[TN] = {})
268 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
270 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
272 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
275 LN == rank && UN == rank && TN <= rank,
276 "MDRangePolicy: Constructor initializer lists have wrong size");
282 MDRangePolicy(point_type
const& lower, point_type
const& upper,
283 tile_type
const& tile = tile_type{})
284 : MDRangePolicy(
typename traits::execution_space(), lower, upper, tile) {}
286 MDRangePolicy(
const typename traits::execution_space& work_space,
287 point_type
const& lower, point_type
const& upper,
288 tile_type
const& tile = tile_type{})
289 : m_space(work_space), m_lower(lower), m_upper(upper), m_tile(tile) {
290 init_helper(Impl::get_tile_size_properties(work_space));
293 template <
typename T, std::size_t NT = rank,
294 typename = std::enable_if_t<std::is_integral<T>::value>>
298 : MDRangePolicy(
typename traits::execution_space(), lower, upper, tile) {}
300 template <
typename T, std::size_t NT = rank,
301 typename = std::enable_if_t<std::is_integral<T>::value>>
302 MDRangePolicy(
const typename traits::execution_space& work_space,
308 Impl::to_array_potentially_narrowing<index_type, decltype(m_lower)>(
310 Impl::to_array_potentially_narrowing<index_type, decltype(m_upper)>(
312 Impl::to_array_potentially_narrowing<index_type, decltype(m_tile)>(
315 template <
class... OtherProperties>
316 MDRangePolicy(
const MDRangePolicy<OtherProperties...> p)
322 m_tile_end(p.m_tile_end),
323 m_num_tiles(p.m_num_tiles),
324 m_prod_tile_dims(p.m_prod_tile_dims),
325 m_tune_tile_size(p.m_tune_tile_size) {}
327 void impl_change_tile_size(
const point_type& tile) {
329 init_helper(Impl::get_tile_size_properties(m_space));
331 bool impl_tune_tile_size()
const {
return m_tune_tile_size; }
334 void init_helper(Impl::TileSizeProperties properties) {
335 m_prod_tile_dims = 1;
339 if (inner_direction == Iterate::Right) {
341 rank_start = rank - 1;
344 for (
int i = rank_start; i != rank_end; i += increment) {
345 const index_type length = m_upper[i] - m_lower[i];
347 if (m_upper[i] < m_lower[i]) {
349 "Kokkos::MDRangePolicy bounds error: The lower bound (" +
350 std::to_string(m_lower[i]) +
") is greater than its upper bound (" +
351 std::to_string(m_upper[i]) +
") in dimension " + std::to_string(i) +
353 #if !defined(KOKKOS_ENABLE_DEPRECATED_CODE_4)
354 Kokkos::abort(msg.c_str());
355 #elif defined(KOKKOS_ENABLE_DEPRECATION_WARNINGS)
356 Kokkos::Impl::log_warning(msg);
360 if (m_tile[i] <= 0) {
361 m_tune_tile_size =
true;
362 if ((inner_direction == Iterate::Right && (i < rank - 1)) ||
363 (inner_direction == Iterate::Left && (i > 0))) {
364 if (m_prod_tile_dims * properties.default_tile_size <
365 static_cast<index_type>(properties.max_total_tile_size)) {
366 m_tile[i] = properties.default_tile_size;
371 m_tile[i] = properties.default_largest_tile_size == 0
372 ? std::max<int>(length, 1)
373 : properties.default_largest_tile_size;
377 static_cast<index_type
>((length + m_tile[i] - 1) / m_tile[i]);
378 m_num_tiles *= m_tile_end[i];
379 m_prod_tile_dims *= m_tile[i];
381 if (m_prod_tile_dims > static_cast<index_type>(properties.max_threads)) {
382 printf(
" Product of tile dimensions exceed maximum limit: %d\n",
383 static_cast<int>(properties.max_threads));
385 "ExecSpace Error: MDRange tile dims exceed maximum number "
386 "of threads per block - choose smaller tile dims");
391 template <
typename LT,
size_t N,
typename UT>
392 MDRangePolicy(
const LT (&)[N],
const UT (&)[N])->MDRangePolicy<Rank<N>>;
394 template <
typename LT,
size_t N,
typename UT,
typename TT,
size_t TN>
395 MDRangePolicy(
const LT (&)[N],
const UT (&)[N],
const TT (&)[TN])
396 ->MDRangePolicy<Rank<N>>;
398 template <
typename LT,
size_t N,
typename UT>
399 MDRangePolicy(DefaultExecutionSpace
const&,
const LT (&)[N],
const UT (&)[N])
400 ->MDRangePolicy<Rank<N>>;
402 template <
typename LT,
size_t N,
typename UT,
typename TT,
size_t TN>
403 MDRangePolicy(DefaultExecutionSpace
const&,
const LT (&)[N],
const UT (&)[N],
405 ->MDRangePolicy<Rank<N>>;
407 template <
typename ES,
typename LT,
size_t N,
typename UT,
408 typename = std::enable_if_t<is_execution_space_v<ES>>>
409 MDRangePolicy(ES
const&,
const LT (&)[N],
const UT (&)[N])
410 ->MDRangePolicy<ES, Rank<N>>;
412 template <
typename ES,
typename LT,
size_t N,
typename UT,
typename TT,
413 size_t TN,
typename = std::enable_if_t<is_execution_space_v<ES>>>
414 MDRangePolicy(ES
const&,
const LT (&)[N],
const UT (&)[N],
const TT (&)[TN])
415 ->MDRangePolicy<ES, Rank<N>>;
417 template <
typename T,
size_t N>
418 MDRangePolicy(Array<T, N>
const&, Array<T, N>
const&)->MDRangePolicy<Rank<N>>;
420 template <
typename T,
size_t N,
size_t NT>
421 MDRangePolicy(Array<T, N>
const&, Array<T, N>
const&, Array<T, NT>
const&)
422 ->MDRangePolicy<Rank<N>>;
424 template <
typename T,
size_t N>
425 MDRangePolicy(DefaultExecutionSpace
const&, Array<T, N>
const&,
427 ->MDRangePolicy<Rank<N>>;
429 template <
typename T,
size_t N,
size_t NT>
430 MDRangePolicy(DefaultExecutionSpace
const&, Array<T, N>
const&,
431 Array<T, N>
const&, Array<T, NT>
const&)
432 ->MDRangePolicy<Rank<N>>;
434 template <
typename ES,
typename T,
size_t N,
435 typename = std::enable_if_t<is_execution_space_v<ES>>>
436 MDRangePolicy(ES
const&, Array<T, N>
const&, Array<T, N>
const&)
437 ->MDRangePolicy<ES, Rank<N>>;
439 template <
typename ES,
typename T,
size_t N,
size_t NT,
440 typename = std::enable_if_t<is_execution_space_v<ES>>>
441 MDRangePolicy(ES
const&, Array<T, N>
const&, Array<T, N>
const&,
443 ->MDRangePolicy<ES, Rank<N>>;
447 #endif // KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
Derived from the C++17 'std::array'. Dropping the iterator interface.
Declaration of various MemoryLayout options.