Kokkos Core Kernels Package  Version of the Day
Kokkos_Serial.hpp
Go to the documentation of this file.
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
47 
48 #ifndef KOKKOS_SERIAL_HPP
49 #define KOKKOS_SERIAL_HPP
50 
51 #include <Kokkos_Macros.hpp>
52 #if defined(KOKKOS_ENABLE_SERIAL)
53 
54 #include <cstddef>
55 #include <iosfwd>
56 #include <Kokkos_Core_fwd.hpp>
57 #include <Kokkos_Parallel.hpp>
58 #include <Kokkos_TaskScheduler.hpp>
59 #include <Kokkos_Layout.hpp>
60 #include <Kokkos_HostSpace.hpp>
61 #include <Kokkos_ScratchSpace.hpp>
62 #include <Kokkos_MemoryTraits.hpp>
63 #include <impl/Kokkos_Tags.hpp>
64 #include <impl/Kokkos_HostThreadTeam.hpp>
65 #include <impl/Kokkos_FunctorAnalysis.hpp>
66 #include <impl/Kokkos_FunctorAdapter.hpp>
67 #include <impl/Kokkos_Tools.hpp>
68 #include <impl/Kokkos_ExecSpaceInitializer.hpp>
69 
70 #include <KokkosExp_MDRangePolicy.hpp>
71 
72 #include <Kokkos_UniqueToken.hpp>
73 
74 namespace Kokkos {
75 
88 class Serial {
89  public:
91 
92 
94  using execution_space = Serial;
96  using memory_space = Kokkos::HostSpace;
98  using size_type = memory_space::size_type;
100  using device_type = Kokkos::Device<execution_space, memory_space>;
101 
103  using array_layout = LayoutRight;
104 
106  using scratch_memory_space = ScratchMemorySpace<Kokkos::Serial>;
107 
109 
116  inline static int in_parallel() { return false; }
117 
124  static void impl_static_fence() {}
125 
126  void fence() const {}
127 
129  static int concurrency() { return 1; }
130 
132  static void print_configuration(std::ostream&,
133  const bool /* detail */ = false) {}
134 
135  static void impl_initialize();
136 
137  static bool impl_is_initialized();
138 
140  static void impl_finalize();
141 
142  //--------------------------------------------------------------------------
143 
144  inline static int impl_thread_pool_size(int = 0) { return 1; }
145  KOKKOS_INLINE_FUNCTION static int impl_thread_pool_rank() { return 0; }
146 
147  //--------------------------------------------------------------------------
148 
149  KOKKOS_INLINE_FUNCTION static unsigned impl_hardware_thread_id() {
150  return impl_thread_pool_rank();
151  }
152  inline static unsigned impl_max_hardware_threads() {
153  return impl_thread_pool_size(0);
154  }
155 
156  uint32_t impl_instance_id() const noexcept { return 0; }
157 
158  static const char* name();
159  //--------------------------------------------------------------------------
160 };
161 
162 namespace Tools {
163 namespace Experimental {
164 template <>
165 struct DeviceTypeTraits<Serial> {
166  static constexpr DeviceType id = DeviceType::Serial;
167 };
168 } // namespace Experimental
169 } // namespace Tools
170 
171 namespace Impl {
172 
173 class SerialSpaceInitializer : public ExecSpaceInitializerBase {
174  public:
175  SerialSpaceInitializer() = default;
176  ~SerialSpaceInitializer() = default;
177  void initialize(const InitArguments& args) final;
178  void finalize(const bool) final;
179  void fence() final;
180  void print_configuration(std::ostream& msg, const bool detail) final;
181 };
182 
183 } // namespace Impl
184 } // namespace Kokkos
185 
186 /*--------------------------------------------------------------------------*/
187 /*--------------------------------------------------------------------------*/
188 
189 namespace Kokkos {
190 namespace Impl {
191 
192 template <>
193 struct MemorySpaceAccess<Kokkos::Serial::memory_space,
194  Kokkos::Serial::scratch_memory_space> {
195  enum : bool { assignable = false };
196  enum : bool { accessible = true };
197  enum : bool { deepcopy = false };
198 };
199 
200 } // namespace Impl
201 } // namespace Kokkos
202 
203 /*--------------------------------------------------------------------------*/
204 /*--------------------------------------------------------------------------*/
205 
206 namespace Kokkos {
207 namespace Impl {
208 
209 // Resize thread team data scratch memory
210 void serial_resize_thread_team_data(size_t pool_reduce_bytes,
211  size_t team_reduce_bytes,
212  size_t team_shared_bytes,
213  size_t thread_local_bytes);
214 
215 HostThreadTeamData* serial_get_thread_team_data();
216 
217 } /* namespace Impl */
218 } /* namespace Kokkos */
219 
220 namespace Kokkos {
221 namespace Impl {
222 
223 /*
224  * < Kokkos::Serial , WorkArgTag >
225  * < WorkArgTag , Impl::enable_if< std::is_same< Kokkos::Serial ,
226  * Kokkos::DefaultExecutionSpace >::value >::type >
227  *
228  */
229 template <class... Properties>
230 class TeamPolicyInternal<Kokkos::Serial, Properties...>
231  : public PolicyTraits<Properties...> {
232  private:
233  size_t m_team_scratch_size[2];
234  size_t m_thread_scratch_size[2];
235  int m_league_size;
236  int m_chunk_size;
237 
238  public:
240  using execution_policy = TeamPolicyInternal;
241 
242  using traits = PolicyTraits<Properties...>;
243 
245  using execution_space = Kokkos::Serial;
246 
247  const typename traits::execution_space& space() const {
248  static typename traits::execution_space m_space;
249  return m_space;
250  }
251 
252  template <class ExecSpace, class... OtherProperties>
253  friend class TeamPolicyInternal;
254 
255  template <class... OtherProperties>
256  TeamPolicyInternal(
257  const TeamPolicyInternal<Kokkos::Serial, OtherProperties...>& p) {
258  m_league_size = p.m_league_size;
259  m_team_scratch_size[0] = p.m_team_scratch_size[0];
260  m_thread_scratch_size[0] = p.m_thread_scratch_size[0];
261  m_team_scratch_size[1] = p.m_team_scratch_size[1];
262  m_thread_scratch_size[1] = p.m_thread_scratch_size[1];
263  m_chunk_size = p.m_chunk_size;
264  }
265 
266  //----------------------------------------
267 
268  template <class FunctorType>
269  int team_size_max(const FunctorType&, const ParallelForTag&) const {
270  return 1;
271  }
272  template <class FunctorType>
273  int team_size_max(const FunctorType&, const ParallelReduceTag&) const {
274  return 1;
275  }
276  template <class FunctorType, class ReducerType>
277  int team_size_max(const FunctorType&, const ReducerType&,
278  const ParallelReduceTag&) const {
279  return 1;
280  }
281  template <class FunctorType>
282  int team_size_recommended(const FunctorType&, const ParallelForTag&) const {
283  return 1;
284  }
285  template <class FunctorType>
286  int team_size_recommended(const FunctorType&,
287  const ParallelReduceTag&) const {
288  return 1;
289  }
290  template <class FunctorType, class ReducerType>
291  int team_size_recommended(const FunctorType&, const ReducerType&,
292  const ParallelReduceTag&) const {
293  return 1;
294  }
295 
296  //----------------------------------------
297 
298  inline int team_size() const { return 1; }
299  inline bool impl_auto_team_size() const { return false; }
300  inline bool impl_auto_vector_length() const { return false; }
301  inline void impl_set_team_size(size_t) {}
302  inline void impl_set_vector_length(size_t) {}
303  inline int league_size() const { return m_league_size; }
304  inline size_t scratch_size(const int& level, int = 0) const {
305  return m_team_scratch_size[level] + m_thread_scratch_size[level];
306  }
307 
308  inline int impl_vector_length() const { return 1; }
309  inline static int vector_length_max() {
310  return 1024;
311  } // Use arbitrary large number, is meant as a vectorizable length
312 
313  inline static int scratch_size_max(int level) {
314  return (level == 0 ? 1024 * 32 : 20 * 1024 * 1024);
315  }
317  TeamPolicyInternal(const execution_space&, int league_size_request,
318  int team_size_request, int /* vector_length_request */ = 1)
319  : m_team_scratch_size{0, 0},
320  m_thread_scratch_size{0, 0},
321  m_league_size(league_size_request),
322  m_chunk_size(32) {
323  if (team_size_request > 1)
324  Kokkos::abort("Kokkos::abort: Requested Team Size is too large!");
325  }
326 
327  TeamPolicyInternal(const execution_space& space, int league_size_request,
328  const Kokkos::AUTO_t& ,
329  int vector_length_request = 1)
330  : TeamPolicyInternal(space, league_size_request, -1,
331  vector_length_request) {}
332 
333  TeamPolicyInternal(const execution_space& space, int league_size_request,
334  const Kokkos::AUTO_t& /* team_size_request */
335  ,
336  const Kokkos::AUTO_t& /* vector_length_request */
337  )
338  : TeamPolicyInternal(space, league_size_request, -1, -1) {}
339 
340  TeamPolicyInternal(const execution_space& space, int league_size_request,
341  int team_size_request,
342  const Kokkos::AUTO_t& /* vector_length_request */
343  )
344  : TeamPolicyInternal(space, league_size_request, team_size_request, -1) {}
345 
346  TeamPolicyInternal(int league_size_request,
347  const Kokkos::AUTO_t& team_size_request,
348  int vector_length_request = 1)
349  : TeamPolicyInternal(typename traits::execution_space(),
350  league_size_request, team_size_request,
351  vector_length_request) {}
352 
353  TeamPolicyInternal(int league_size_request,
354  const Kokkos::AUTO_t& team_size_request,
355  const Kokkos::AUTO_t& vector_length_request)
356  : TeamPolicyInternal(typename traits::execution_space(),
357  league_size_request, team_size_request,
358  vector_length_request) {}
359  TeamPolicyInternal(int league_size_request, int team_size_request,
360  const Kokkos::AUTO_t& vector_length_request)
361  : TeamPolicyInternal(typename traits::execution_space(),
362  league_size_request, team_size_request,
363  vector_length_request) {}
364 
365  TeamPolicyInternal(int league_size_request, int team_size_request,
366  int vector_length_request = 1)
367  : TeamPolicyInternal(typename traits::execution_space(),
368  league_size_request, team_size_request,
369  vector_length_request) {}
370 
371  inline int chunk_size() const { return m_chunk_size; }
372 
374  inline TeamPolicyInternal& set_chunk_size(
375  typename traits::index_type chunk_size_) {
376  m_chunk_size = chunk_size_;
377  return *this;
378  }
379 
382  inline TeamPolicyInternal& set_scratch_size(const int& level,
383  const PerTeamValue& per_team) {
384  m_team_scratch_size[level] = per_team.value;
385  return *this;
386  }
387 
390  inline TeamPolicyInternal& set_scratch_size(
391  const int& level, const PerThreadValue& per_thread) {
392  m_thread_scratch_size[level] = per_thread.value;
393  return *this;
394  }
395 
398  inline TeamPolicyInternal& set_scratch_size(
399  const int& level, const PerTeamValue& per_team,
400  const PerThreadValue& per_thread) {
401  m_team_scratch_size[level] = per_team.value;
402  m_thread_scratch_size[level] = per_thread.value;
403  return *this;
404  }
405 
406  using member_type = Impl::HostThreadTeamMember<Kokkos::Serial>;
407 };
408 } /* namespace Impl */
409 } /* namespace Kokkos */
410 
411 /*--------------------------------------------------------------------------*/
412 /*--------------------------------------------------------------------------*/
413 /* Parallel patterns for Kokkos::Serial with RangePolicy */
414 
415 namespace Kokkos {
416 namespace Impl {
417 
418 template <class FunctorType, class... Traits>
419 class ParallelFor<FunctorType, Kokkos::RangePolicy<Traits...>, Kokkos::Serial> {
420  private:
421  using Policy = Kokkos::RangePolicy<Traits...>;
422 
423  const FunctorType m_functor;
424  const Policy m_policy;
425 
426  template <class TagType>
427  typename std::enable_if<std::is_same<TagType, void>::value>::type exec()
428  const {
429  const typename Policy::member_type e = m_policy.end();
430  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
431  m_functor(i);
432  }
433  }
434 
435  template <class TagType>
436  typename std::enable_if<!std::is_same<TagType, void>::value>::type exec()
437  const {
438  const TagType t{};
439  const typename Policy::member_type e = m_policy.end();
440  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
441  m_functor(t, i);
442  }
443  }
444 
445  public:
446  inline void execute() const {
447  this->template exec<typename Policy::work_tag>();
448  }
449 
450  inline ParallelFor(const FunctorType& arg_functor, const Policy& arg_policy)
451  : m_functor(arg_functor), m_policy(arg_policy) {}
452 };
453 
454 /*--------------------------------------------------------------------------*/
455 
456 template <class FunctorType, class ReducerType, class... Traits>
457 class ParallelReduce<FunctorType, Kokkos::RangePolicy<Traits...>, ReducerType,
458  Kokkos::Serial> {
459  private:
460  using Policy = Kokkos::RangePolicy<Traits...>;
461  using WorkTag = typename Policy::work_tag;
462 
463  using ReducerConditional =
464  Kokkos::Impl::if_c<std::is_same<InvalidType, ReducerType>::value,
465  FunctorType, ReducerType>;
466 
467  using ReducerTypeFwd = typename ReducerConditional::type;
468  using WorkTagFwd =
469  std::conditional_t<std::is_same<InvalidType, ReducerType>::value, WorkTag,
470  void>;
471 
472  using Analysis =
473  FunctorAnalysis<FunctorPatternInterface::REDUCE, Policy, FunctorType>;
474 
475  using ValueInit = Kokkos::Impl::FunctorValueInit<ReducerTypeFwd, WorkTagFwd>;
476 
477  using pointer_type = typename Analysis::pointer_type;
478  using reference_type = typename Analysis::reference_type;
479 
480  const FunctorType m_functor;
481  const Policy m_policy;
482  const ReducerType m_reducer;
483  const pointer_type m_result_ptr;
484 
485  template <class TagType>
486  inline typename std::enable_if<std::is_same<TagType, void>::value>::type exec(
487  reference_type update) const {
488  const typename Policy::member_type e = m_policy.end();
489  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
490  m_functor(i, update);
491  }
492  }
493 
494  template <class TagType>
495  inline typename std::enable_if<!std::is_same<TagType, void>::value>::type
496  exec(reference_type update) const {
497  const TagType t{};
498 
499  const typename Policy::member_type e = m_policy.end();
500  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
501  m_functor(t, i, update);
502  }
503  }
504 
505  public:
506  inline void execute() const {
507  const size_t pool_reduce_size =
508  Analysis::value_size(ReducerConditional::select(m_functor, m_reducer));
509  const size_t team_reduce_size = 0; // Never shrinks
510  const size_t team_shared_size = 0; // Never shrinks
511  const size_t thread_local_size = 0; // Never shrinks
512 
513  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
514  team_shared_size, thread_local_size);
515 
516  HostThreadTeamData& data = *serial_get_thread_team_data();
517 
518  pointer_type ptr =
519  m_result_ptr ? m_result_ptr : pointer_type(data.pool_reduce_local());
520 
521  reference_type update =
522  ValueInit::init(ReducerConditional::select(m_functor, m_reducer), ptr);
523 
524  this->template exec<WorkTag>(update);
525 
526  Kokkos::Impl::FunctorFinal<ReducerTypeFwd, WorkTagFwd>::final(
527  ReducerConditional::select(m_functor, m_reducer), ptr);
528  }
529 
530  template <class HostViewType>
531  ParallelReduce(
532  const FunctorType& arg_functor, const Policy& arg_policy,
533  const HostViewType& arg_result_view,
534  typename std::enable_if<Kokkos::is_view<HostViewType>::value &&
535  !Kokkos::is_reducer_type<ReducerType>::value,
536  void*>::type = nullptr)
537  : m_functor(arg_functor),
538  m_policy(arg_policy),
539  m_reducer(InvalidType()),
540  m_result_ptr(arg_result_view.data()) {
541  static_assert(Kokkos::is_view<HostViewType>::value,
542  "Kokkos::Serial reduce result must be a View");
543 
544  static_assert(
545  Kokkos::Impl::MemorySpaceAccess<typename HostViewType::memory_space,
546  Kokkos::HostSpace>::accessible,
547  "Kokkos::Serial reduce result must be a View in HostSpace");
548  }
549 
550  inline ParallelReduce(const FunctorType& arg_functor, Policy arg_policy,
551  const ReducerType& reducer)
552  : m_functor(arg_functor),
553  m_policy(arg_policy),
554  m_reducer(reducer),
555  m_result_ptr(reducer.view().data()) {
556  /*static_assert( std::is_same< typename ViewType::memory_space
557  , Kokkos::HostSpace >::value
558  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace"
559  );*/
560  }
561 };
562 
563 /*--------------------------------------------------------------------------*/
564 
565 template <class FunctorType, class... Traits>
566 class ParallelScan<FunctorType, Kokkos::RangePolicy<Traits...>,
567  Kokkos::Serial> {
568  private:
569  using Policy = Kokkos::RangePolicy<Traits...>;
570  using WorkTag = typename Policy::work_tag;
571 
572  using Analysis =
573  FunctorAnalysis<FunctorPatternInterface::SCAN, Policy, FunctorType>;
574 
575  using ValueInit = Kokkos::Impl::FunctorValueInit<FunctorType, WorkTag>;
576 
577  using pointer_type = typename Analysis::pointer_type;
578  using reference_type = typename Analysis::reference_type;
579 
580  const FunctorType m_functor;
581  const Policy m_policy;
582 
583  template <class TagType>
584  inline typename std::enable_if<std::is_same<TagType, void>::value>::type exec(
585  reference_type update) const {
586  const typename Policy::member_type e = m_policy.end();
587  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
588  m_functor(i, update, true);
589  }
590  }
591 
592  template <class TagType>
593  inline typename std::enable_if<!std::is_same<TagType, void>::value>::type
594  exec(reference_type update) const {
595  const TagType t{};
596  const typename Policy::member_type e = m_policy.end();
597  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
598  m_functor(t, i, update, true);
599  }
600  }
601 
602  public:
603  inline void execute() const {
604  const size_t pool_reduce_size = Analysis::value_size(m_functor);
605  const size_t team_reduce_size = 0; // Never shrinks
606  const size_t team_shared_size = 0; // Never shrinks
607  const size_t thread_local_size = 0; // Never shrinks
608 
609  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
610  team_shared_size, thread_local_size);
611 
612  HostThreadTeamData& data = *serial_get_thread_team_data();
613 
614  reference_type update =
615  ValueInit::init(m_functor, pointer_type(data.pool_reduce_local()));
616 
617  this->template exec<WorkTag>(update);
618  }
619 
620  inline ParallelScan(const FunctorType& arg_functor, const Policy& arg_policy)
621  : m_functor(arg_functor), m_policy(arg_policy) {}
622 };
623 
624 /*--------------------------------------------------------------------------*/
625 template <class FunctorType, class ReturnType, class... Traits>
626 class ParallelScanWithTotal<FunctorType, Kokkos::RangePolicy<Traits...>,
627  ReturnType, Kokkos::Serial> {
628  private:
629  using Policy = Kokkos::RangePolicy<Traits...>;
630  using WorkTag = typename Policy::work_tag;
631 
632  using Analysis =
633  FunctorAnalysis<FunctorPatternInterface::SCAN, Policy, FunctorType>;
634 
635  using ValueInit = Kokkos::Impl::FunctorValueInit<FunctorType, WorkTag>;
636 
637  using pointer_type = typename Analysis::pointer_type;
638  using reference_type = typename Analysis::reference_type;
639 
640  const FunctorType m_functor;
641  const Policy m_policy;
642  ReturnType& m_returnvalue;
643 
644  template <class TagType>
645  inline typename std::enable_if<std::is_same<TagType, void>::value>::type exec(
646  reference_type update) const {
647  const typename Policy::member_type e = m_policy.end();
648  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
649  m_functor(i, update, true);
650  }
651  }
652 
653  template <class TagType>
654  inline typename std::enable_if<!std::is_same<TagType, void>::value>::type
655  exec(reference_type update) const {
656  const TagType t{};
657  const typename Policy::member_type e = m_policy.end();
658  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
659  m_functor(t, i, update, true);
660  }
661  }
662 
663  public:
664  inline void execute() {
665  const size_t pool_reduce_size = Analysis::value_size(m_functor);
666  const size_t team_reduce_size = 0; // Never shrinks
667  const size_t team_shared_size = 0; // Never shrinks
668  const size_t thread_local_size = 0; // Never shrinks
669 
670  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
671  team_shared_size, thread_local_size);
672 
673  HostThreadTeamData& data = *serial_get_thread_team_data();
674 
675  reference_type update =
676  ValueInit::init(m_functor, pointer_type(data.pool_reduce_local()));
677 
678  this->template exec<WorkTag>(update);
679 
680  m_returnvalue = update;
681  }
682 
683  inline ParallelScanWithTotal(const FunctorType& arg_functor,
684  const Policy& arg_policy,
685  ReturnType& arg_returnvalue)
686  : m_functor(arg_functor),
687  m_policy(arg_policy),
688  m_returnvalue(arg_returnvalue) {}
689 };
690 
691 } // namespace Impl
692 } // namespace Kokkos
693 
694 /*--------------------------------------------------------------------------*/
695 /*--------------------------------------------------------------------------*/
696 /* Parallel patterns for Kokkos::Serial with MDRangePolicy */
697 
698 namespace Kokkos {
699 namespace Impl {
700 
701 template <class FunctorType, class... Traits>
702 class ParallelFor<FunctorType, Kokkos::MDRangePolicy<Traits...>,
703  Kokkos::Serial> {
704  private:
705  using MDRangePolicy = Kokkos::MDRangePolicy<Traits...>;
706  using Policy = typename MDRangePolicy::impl_range_policy;
707 
708  using iterate_type = typename Kokkos::Impl::HostIterateTile<
709  MDRangePolicy, FunctorType, typename MDRangePolicy::work_tag, void>;
710 
711  const FunctorType m_functor;
712  const MDRangePolicy m_mdr_policy;
713  const Policy m_policy;
714 
715  void exec() const {
716  const typename Policy::member_type e = m_policy.end();
717  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
718  iterate_type(m_mdr_policy, m_functor)(i);
719  }
720  }
721 
722  public:
723  inline void execute() const { this->exec(); }
724  template <typename Policy, typename Functor>
725  static int max_tile_size_product(const Policy&, const Functor&) {
731  return 1024;
732  }
733  inline ParallelFor(const FunctorType& arg_functor,
734  const MDRangePolicy& arg_policy)
735  : m_functor(arg_functor),
736  m_mdr_policy(arg_policy),
737  m_policy(Policy(0, m_mdr_policy.m_num_tiles).set_chunk_size(1)) {}
738 };
739 
740 template <class FunctorType, class ReducerType, class... Traits>
741 class ParallelReduce<FunctorType, Kokkos::MDRangePolicy<Traits...>, ReducerType,
742  Kokkos::Serial> {
743  private:
744  using MDRangePolicy = Kokkos::MDRangePolicy<Traits...>;
745  using Policy = typename MDRangePolicy::impl_range_policy;
746 
747  using WorkTag = typename MDRangePolicy::work_tag;
748 
749  using ReducerConditional =
750  Kokkos::Impl::if_c<std::is_same<InvalidType, ReducerType>::value,
751  FunctorType, ReducerType>;
752  using ReducerTypeFwd = typename ReducerConditional::type;
753  using WorkTagFwd =
754  std::conditional_t<std::is_same<InvalidType, ReducerType>::value, WorkTag,
755  void>;
756 
757  using Analysis = FunctorAnalysis<FunctorPatternInterface::REDUCE,
758  MDRangePolicy, FunctorType>;
759 
760  using ValueInit = Kokkos::Impl::FunctorValueInit<ReducerTypeFwd, WorkTagFwd>;
761 
762  using pointer_type = typename Analysis::pointer_type;
763  using value_type = typename Analysis::value_type;
764  using reference_type = typename Analysis::reference_type;
765 
766  using iterate_type =
767  typename Kokkos::Impl::HostIterateTile<MDRangePolicy, FunctorType,
768  WorkTag, reference_type>;
769 
770  const FunctorType m_functor;
771  const MDRangePolicy m_mdr_policy;
772  const Policy m_policy;
773  const ReducerType m_reducer;
774  const pointer_type m_result_ptr;
775 
776  inline void exec(reference_type update) const {
777  const typename Policy::member_type e = m_policy.end();
778  for (typename Policy::member_type i = m_policy.begin(); i < e; ++i) {
779  iterate_type(m_mdr_policy, m_functor, update)(i);
780  }
781  }
782 
783  public:
784  template <typename Policy, typename Functor>
785  static int max_tile_size_product(const Policy&, const Functor&) {
791  return 1024;
792  }
793  inline void execute() const {
794  const size_t pool_reduce_size =
795  Analysis::value_size(ReducerConditional::select(m_functor, m_reducer));
796  const size_t team_reduce_size = 0; // Never shrinks
797  const size_t team_shared_size = 0; // Never shrinks
798  const size_t thread_local_size = 0; // Never shrinks
799 
800  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
801  team_shared_size, thread_local_size);
802 
803  HostThreadTeamData& data = *serial_get_thread_team_data();
804 
805  pointer_type ptr =
806  m_result_ptr ? m_result_ptr : pointer_type(data.pool_reduce_local());
807 
808  reference_type update =
809  ValueInit::init(ReducerConditional::select(m_functor, m_reducer), ptr);
810 
811  this->exec(update);
812 
813  Kokkos::Impl::FunctorFinal<ReducerTypeFwd, WorkTagFwd>::final(
814  ReducerConditional::select(m_functor, m_reducer), ptr);
815  }
816 
817  template <class HostViewType>
818  ParallelReduce(
819  const FunctorType& arg_functor, const MDRangePolicy& arg_policy,
820  const HostViewType& arg_result_view,
821  typename std::enable_if<Kokkos::is_view<HostViewType>::value &&
822  !Kokkos::is_reducer_type<ReducerType>::value,
823  void*>::type = nullptr)
824  : m_functor(arg_functor),
825  m_mdr_policy(arg_policy),
826  m_policy(Policy(0, m_mdr_policy.m_num_tiles).set_chunk_size(1)),
827  m_reducer(InvalidType()),
828  m_result_ptr(arg_result_view.data()) {
829  static_assert(Kokkos::is_view<HostViewType>::value,
830  "Kokkos::Serial reduce result must be a View");
831 
832  static_assert(
833  Kokkos::Impl::MemorySpaceAccess<typename HostViewType::memory_space,
834  Kokkos::HostSpace>::accessible,
835  "Kokkos::Serial reduce result must be a View in HostSpace");
836  }
837 
838  inline ParallelReduce(const FunctorType& arg_functor,
839  MDRangePolicy arg_policy, const ReducerType& reducer)
840  : m_functor(arg_functor),
841  m_mdr_policy(arg_policy),
842  m_policy(Policy(0, m_mdr_policy.m_num_tiles).set_chunk_size(1)),
843  m_reducer(reducer),
844  m_result_ptr(reducer.view().data()) {
845  /*static_assert( std::is_same< typename ViewType::memory_space
846  , Kokkos::HostSpace >::value
847  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace"
848  );*/
849  }
850 };
851 
852 } // namespace Impl
853 } // namespace Kokkos
854 
855 /*--------------------------------------------------------------------------*/
856 /*--------------------------------------------------------------------------*/
857 /* Parallel patterns for Kokkos::Serial with TeamPolicy */
858 
859 namespace Kokkos {
860 namespace Impl {
861 
862 template <class FunctorType, class... Properties>
863 class ParallelFor<FunctorType, Kokkos::TeamPolicy<Properties...>,
864  Kokkos::Serial> {
865  private:
866  enum { TEAM_REDUCE_SIZE = 512 };
867 
868  using Policy = TeamPolicyInternal<Kokkos::Serial, Properties...>;
869  using Member = typename Policy::member_type;
870 
871  const FunctorType m_functor;
872  const int m_league;
873  const int m_shared;
874 
875  template <class TagType>
876  inline typename std::enable_if<std::is_same<TagType, void>::value>::type exec(
877  HostThreadTeamData& data) const {
878  for (int ileague = 0; ileague < m_league; ++ileague) {
879  m_functor(Member(data, ileague, m_league));
880  }
881  }
882 
883  template <class TagType>
884  inline typename std::enable_if<!std::is_same<TagType, void>::value>::type
885  exec(HostThreadTeamData& data) const {
886  const TagType t{};
887  for (int ileague = 0; ileague < m_league; ++ileague) {
888  m_functor(t, Member(data, ileague, m_league));
889  }
890  }
891 
892  public:
893  inline void execute() const {
894  const size_t pool_reduce_size = 0; // Never shrinks
895  const size_t team_reduce_size = TEAM_REDUCE_SIZE;
896  const size_t team_shared_size = m_shared;
897  const size_t thread_local_size = 0; // Never shrinks
898 
899  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
900  team_shared_size, thread_local_size);
901 
902  HostThreadTeamData& data = *serial_get_thread_team_data();
903 
904  this->template exec<typename Policy::work_tag>(data);
905  }
906 
907  ParallelFor(const FunctorType& arg_functor, const Policy& arg_policy)
908  : m_functor(arg_functor),
909  m_league(arg_policy.league_size()),
910  m_shared(arg_policy.scratch_size(0) + arg_policy.scratch_size(1) +
911  FunctorTeamShmemSize<FunctorType>::value(arg_functor, 1)) {}
912 };
913 
914 /*--------------------------------------------------------------------------*/
915 
916 template <class FunctorType, class ReducerType, class... Properties>
917 class ParallelReduce<FunctorType, Kokkos::TeamPolicy<Properties...>,
918  ReducerType, Kokkos::Serial> {
919  private:
920  enum { TEAM_REDUCE_SIZE = 512 };
921 
922  using Policy = TeamPolicyInternal<Kokkos::Serial, Properties...>;
923 
924  using Analysis =
925  FunctorAnalysis<FunctorPatternInterface::REDUCE, Policy, FunctorType>;
926 
927  using Member = typename Policy::member_type;
928  using WorkTag = typename Policy::work_tag;
929 
930  using ReducerConditional =
931  Kokkos::Impl::if_c<std::is_same<InvalidType, ReducerType>::value,
932  FunctorType, ReducerType>;
933  using ReducerTypeFwd = typename ReducerConditional::type;
934  using WorkTagFwd =
935  std::conditional_t<std::is_same<InvalidType, ReducerType>::value, WorkTag,
936  void>;
937 
938  using ValueInit = Kokkos::Impl::FunctorValueInit<ReducerTypeFwd, WorkTagFwd>;
939 
940  using pointer_type = typename Analysis::pointer_type;
941  using reference_type = typename Analysis::reference_type;
942 
943  const FunctorType m_functor;
944  const int m_league;
945  const ReducerType m_reducer;
946  pointer_type m_result_ptr;
947  const int m_shared;
948 
949  template <class TagType>
950  inline typename std::enable_if<std::is_same<TagType, void>::value>::type exec(
951  HostThreadTeamData& data, reference_type update) const {
952  for (int ileague = 0; ileague < m_league; ++ileague) {
953  m_functor(Member(data, ileague, m_league), update);
954  }
955  }
956 
957  template <class TagType>
958  inline typename std::enable_if<!std::is_same<TagType, void>::value>::type
959  exec(HostThreadTeamData& data, reference_type update) const {
960  const TagType t{};
961 
962  for (int ileague = 0; ileague < m_league; ++ileague) {
963  m_functor(t, Member(data, ileague, m_league), update);
964  }
965  }
966 
967  public:
968  inline void execute() const {
969  const size_t pool_reduce_size =
970  Analysis::value_size(ReducerConditional::select(m_functor, m_reducer));
971 
972  const size_t team_reduce_size = TEAM_REDUCE_SIZE;
973  const size_t team_shared_size = m_shared;
974  const size_t thread_local_size = 0; // Never shrinks
975 
976  serial_resize_thread_team_data(pool_reduce_size, team_reduce_size,
977  team_shared_size, thread_local_size);
978 
979  HostThreadTeamData& data = *serial_get_thread_team_data();
980 
981  pointer_type ptr =
982  m_result_ptr ? m_result_ptr : pointer_type(data.pool_reduce_local());
983 
984  reference_type update =
985  ValueInit::init(ReducerConditional::select(m_functor, m_reducer), ptr);
986 
987  this->template exec<WorkTag>(data, update);
988 
989  Kokkos::Impl::FunctorFinal<ReducerTypeFwd, WorkTagFwd>::final(
990  ReducerConditional::select(m_functor, m_reducer), ptr);
991  }
992 
993  template <class ViewType>
994  ParallelReduce(
995  const FunctorType& arg_functor, const Policy& arg_policy,
996  const ViewType& arg_result,
997  typename std::enable_if<Kokkos::is_view<ViewType>::value &&
998  !Kokkos::is_reducer_type<ReducerType>::value,
999  void*>::type = nullptr)
1000  : m_functor(arg_functor),
1001  m_league(arg_policy.league_size()),
1002  m_reducer(InvalidType()),
1003  m_result_ptr(arg_result.data()),
1004  m_shared(arg_policy.scratch_size(0) + arg_policy.scratch_size(1) +
1005  FunctorTeamShmemSize<FunctorType>::value(m_functor, 1)) {
1006  static_assert(Kokkos::is_view<ViewType>::value,
1007  "Reduction result on Kokkos::Serial must be a Kokkos::View");
1008 
1009  static_assert(
1010  Kokkos::Impl::MemorySpaceAccess<typename ViewType::memory_space,
1011  Kokkos::HostSpace>::accessible,
1012  "Reduction result on Kokkos::Serial must be a Kokkos::View in "
1013  "HostSpace");
1014  }
1015 
1016  inline ParallelReduce(const FunctorType& arg_functor, Policy arg_policy,
1017  const ReducerType& reducer)
1018  : m_functor(arg_functor),
1019  m_league(arg_policy.league_size()),
1020  m_reducer(reducer),
1021  m_result_ptr(reducer.view().data()),
1022  m_shared(arg_policy.scratch_size(0) + arg_policy.scratch_size(1) +
1023  FunctorTeamShmemSize<FunctorType>::value(arg_functor, 1)) {
1024  /*static_assert( std::is_same< typename ViewType::memory_space
1025  , Kokkos::HostSpace >::value
1026  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace"
1027  );*/
1028  }
1029 };
1030 
1031 } // namespace Impl
1032 } // namespace Kokkos
1033 
1034 /*--------------------------------------------------------------------------*/
1035 /*--------------------------------------------------------------------------*/
1036 
1037 namespace Kokkos {
1038 namespace Experimental {
1039 
1040 template <>
1041 class UniqueToken<Serial, UniqueTokenScope::Instance> {
1042  public:
1043  using execution_space = Serial;
1044  using size_type = int;
1045 
1049  UniqueToken(execution_space const& = execution_space()) noexcept {}
1050 
1054  UniqueToken(size_type, execution_space const& = execution_space()) {}
1055 
1057  KOKKOS_INLINE_FUNCTION
1058  int size() const noexcept { return 1; }
1059 
1061  KOKKOS_INLINE_FUNCTION
1062  int acquire() const noexcept { return 0; }
1063 
1065  KOKKOS_INLINE_FUNCTION
1066  void release(int) const noexcept {}
1067 };
1068 
1069 template <>
1070 class UniqueToken<Serial, UniqueTokenScope::Global> {
1071  public:
1072  using execution_space = Serial;
1073  using size_type = int;
1074 
1078  UniqueToken(execution_space const& = execution_space()) noexcept {}
1079 
1081  KOKKOS_INLINE_FUNCTION
1082  int size() const noexcept { return 1; }
1083 
1085  KOKKOS_INLINE_FUNCTION
1086  int acquire() const noexcept { return 0; }
1087 
1089  KOKKOS_INLINE_FUNCTION
1090  void release(int) const noexcept {}
1091 };
1092 
1093 } // namespace Experimental
1094 } // namespace Kokkos
1095 
1096 #include <impl/Kokkos_Serial_Task.hpp>
1097 
1098 #endif // defined( KOKKOS_ENABLE_SERIAL )
1099 #endif /* #define KOKKOS_SERIAL_HPP */
Memory management for host memory.
Declaration of various MemoryLayout options.
Declaration of parallel operators.
ReturnType
Execution policy for work over a range of an integral type.
Definition: dummy.cpp:3
Access relationship between DstMemorySpace and SrcMemorySpace.