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
74namespace Kokkos {
75
88class 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
162namespace Tools {
163namespace Experimental {
164template <>
165struct DeviceTypeTraits<Serial> {
166 static constexpr DeviceType id = DeviceType::Serial;
167};
168} // namespace Experimental
169} // namespace Tools
170
171namespace Impl {
172
173class 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
189namespace Kokkos {
190namespace Impl {
191
192template <>
193struct 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
206namespace Kokkos {
207namespace Impl {
208
209// Resize thread team data scratch memory
210void 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
215HostThreadTeamData* serial_get_thread_team_data();
216
217} /* namespace Impl */
218} /* namespace Kokkos */
219
220namespace Kokkos {
221namespace Impl {
222
223/*
224 * < Kokkos::Serial , WorkArgTag >
225 * < WorkArgTag , Impl::enable_if< std::is_same< Kokkos::Serial ,
226 * Kokkos::DefaultExecutionSpace >::value >::type >
227 *
228 */
229template <class... Properties>
230class 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
415namespace Kokkos {
416namespace Impl {
417
418template <class FunctorType, class... Traits>
419class 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
456template <class FunctorType, class ReducerType, class... Traits>
457class 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
565template <class FunctorType, class... Traits>
566class 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/*--------------------------------------------------------------------------*/
625template <class FunctorType, class ReturnType, class... Traits>
626class 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
698namespace Kokkos {
699namespace Impl {
700
701template <class FunctorType, class... Traits>
702class 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
740template <class FunctorType, class ReducerType, class... Traits>
741class 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
859namespace Kokkos {
860namespace Impl {
861
862template <class FunctorType, class... Properties>
863class 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
916template <class FunctorType, class ReducerType, class... Properties>
917class 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
1037namespace Kokkos {
1038namespace Experimental {
1039
1040template <>
1041class 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
1069template <>
1070class 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 */
Declaration of various MemoryLayout options.
Declaration of parallel operators.
Memory management for host memory.
Execution policy for work over a range of an integral type.
ReturnType
Access relationship between DstMemorySpace and SrcMemorySpace.