Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_withLocalAccess.hpp
Go to the documentation of this file.
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Tpetra: Templated Linear Algebra Services Package
6 // Copyright (2008) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // ************************************************************************
39 // @HEADER
40 */
41 
42 #ifndef TPETRA_WITHLOCALACCESS_HPP
43 #define TPETRA_WITHLOCALACCESS_HPP
44 
45 #include "TpetraCore_config.h"
46 #include "Tpetra_Access.hpp"
47 #include <functional>
48 #include <type_traits>
49 
53 
54 namespace Tpetra {
55 
57  // Generic classes needed to implement withLocalAccess
59 
60  namespace Details {
61  template<class T> struct is_access_mode : public std::false_type {};
62  template<> struct is_access_mode<Access::ReadOnly> : public std::true_type {};
63  template<> struct is_access_mode<Access::ReadWrite> : public std::true_type {};
64  template<> struct is_access_mode<Access::WriteOnly> : public std::true_type {};
65 
72  template<class GlobalObjectType>
74  using type = typename GlobalObjectType::device_type::memory_space;
75 
76  // Given a global object, get its (default) memory space instance.
77  static type space (const GlobalObjectType& /* G */) {
78  // This stub just assumes that 'type' is default constructible.
79  // In Kokkos, default-constructing a memory space instance just
80  // gives the default memory space.
81  return type ();
82  }
83  };
84 
91  template<class GlobalObjectType>
93  using type = typename GlobalObjectType::device_type::execution_space;
94 
95  // Given a global object, get its (default) execution space instance.
96  static type space (const GlobalObjectType& /* G */) {
97  // This stub just assumes that 'type' is default constructible.
98  // In Kokkos, default-constructing a execution space instance just
99  // gives the default execution space.
100  return type ();
101  }
102  };
103 
104 #ifndef DOXYGEN_SHOULD_SKIP_THIS
105  template<class GlobalObjectType, class ... Args>
106  class LocalAccess; // forward declaration
107 #endif // DOXYGEN_SHOULD_SKIP_THIS
108 
126  template<class LocalAccessType>
128 
147  template<class LocalAccessType>
149  master_local_object_type
150  getMasterLocalObject (LocalAccessType LA) {
152  }
153 
178  template<class LocalAccessType>
180 
191  template<class LocalAccessType>
193  nonowning_local_object_type
194  getNonowningLocalObject(LocalAccessType LA,
196  master_local_object_type& master)
197  {
199  return impl_type::get(LA, master);
200  }
201  } // namespace Details
202 
217  template<class LocalAccessType>
219  typename Details::GetNonowningLocalObject<LocalAccessType>::
220  nonowning_local_object_type;
221 
223  // Users call readOnly, writeOnly, and readWrite, in order to declare
224  // how they intend to access a global object's local data.
226 
229  template<class GlobalObjectType>
231  GlobalObjectType,
232  Access::ReadOnly>
233  readOnly (GlobalObjectType&);
234 
238  template<class GlobalObjectType>
240  GlobalObjectType,
241  Access::ReadOnly>
242  readOnly (const GlobalObjectType&);
243 
246  template<class GlobalObjectType>
248  GlobalObjectType,
249  Access::WriteOnly>
250  writeOnly (GlobalObjectType&);
251 
254  template<class GlobalObjectType>
256  GlobalObjectType,
257  Access::ReadWrite>
258  readWrite (GlobalObjectType&);
259 
261  // LocalAccess struct
263 
264  namespace Details {
266  struct unspecified_type {};
267 
276  template<class ... Args>
277  struct LocalAccessTraits {};
278 
279  // An empty list of template arguments constrains nothing.
280  template<>
281  struct LocalAccessTraits<> {
282  using execution_space = unspecified_type;
283  using memory_space = unspecified_type;
284  using access_mode = unspecified_type;
285  };
286 
287  // Skip over any instances of unspecified_type. This makes it
288  // easy to define the return types of LocalAccess::on and
289  // LocalAccess::at (see below).
290  template<class ... Rest>
291  struct LocalAccessTraits<unspecified_type, Rest...> {
292  private:
293  using rest_type = LocalAccessTraits<Rest...>;
294  public:
295  using execution_space = typename rest_type::execution_space;
296  using memory_space = typename rest_type::memory_space;
297  using access_mode = typename rest_type::access_mode;
298  };
299 
300  template<class First, class ... Rest>
301  struct LocalAccessTraits<First, Rest...> {
302  private:
303  using rest_type = LocalAccessTraits<Rest...>;
304  public:
305  using execution_space = typename std::conditional<
306  Kokkos::Impl::is_execution_space<First>::value,
307  First,
308  typename rest_type::execution_space>::type;
309  using memory_space = typename std::conditional<
310  Kokkos::Impl::is_memory_space<First>::value,
311  First,
312  typename rest_type::memory_space>::type;
313  using access_mode = typename std::conditional<
314  is_access_mode<First>::value,
315  First,
316  typename rest_type::access_mode>::type;
317  };
318 
319  template<class GlobalObjectType,
320  class Traits,
321  bool is_execution_space_specified = ! std::is_same<
322  typename Traits::execution_space,
323  unspecified_type>::value,
324  bool is_memory_space_specified = ! std::is_same<
325  typename Traits::memory_space,
326  unspecified_type>::value>
327  struct SpaceTypes {};
328 
329  template<class GlobalObjectType, class Traits>
330  struct SpaceTypes<GlobalObjectType, Traits, true, true> {
331  using execution_space = typename Traits::execution_space;
332  using memory_space = typename Traits::memory_space;
333  };
334 
335  // If only memory_space was specified, then get execution_space
336  // from memory_space's default execution space.
337  template<class GlobalObjectType, class Traits>
338  struct SpaceTypes<GlobalObjectType, Traits, false, true> {
339  using execution_space =
340  typename Traits::memory_space::execution_space;
341  using memory_space = typename Traits::memory_space;
342  };
343 
344  // If only execution_space was specified, then get memory_space
345  // from execution_space's default memory space.
346  template<class GlobalObjectType, class Traits>
347  struct SpaceTypes<GlobalObjectType, Traits, true, false> {
348  using execution_space = typename Traits::execution_space;
349  using memory_space =
350  typename Traits::execution_space::memory_space;
351  };
352 
353  // If neither execution_space nor memory_space were specified,
354  // then get them both from their defaults, that depend on
355  // GlobalObjectType.
356  template<class GlobalObjectType, class Traits>
357  struct SpaceTypes<GlobalObjectType, Traits, false, false> {
358  using execution_space =
359  typename DefaultExecutionSpace<GlobalObjectType>::type;
360  using memory_space =
361  typename DefaultMemorySpace<GlobalObjectType>::type;
362  };
363 
431  template<class GlobalObjectType, class ... Args>
432  class LocalAccess {
433  private:
434  using this_type = LocalAccess<GlobalObjectType, Args...>;
435  using traits = LocalAccessTraits<Args...>;
436  static constexpr bool is_execution_space_specified =
437  ! std::is_same<typename traits::execution_space,
438  unspecified_type>::value;
439  static constexpr bool is_memory_space_specified =
440  ! std::is_same<typename traits::memory_space,
441  unspecified_type>::value;
442  static constexpr bool is_access_mode_specified =
443  ! std::is_same<typename traits::access_mode,
444  unspecified_type>::value;
445  static_assert(is_access_mode_specified, "LocalAccess requires "
446  "that you specify the access mode. You may do this by "
447  "always starting construction of a LocalAccess instance "
448  "with readOnly, writeOnly, or readWrite.");
449 
450  public:
451  using global_object_type = GlobalObjectType;
452 
453  using execution_space =
454  typename SpaceTypes<global_object_type, traits>::execution_space;
455  static_assert(! is_execution_space_specified ||
456  Kokkos::Impl::is_execution_space<execution_space>::value,
457  "Specified execution space is not a Kokkos execution space.");
458  static_assert(is_execution_space_specified ||
459  Kokkos::Impl::is_execution_space<execution_space>::value,
460  "Default execution space is not a Kokkos execution space.");
461 
462  using memory_space =
463  typename SpaceTypes<global_object_type, traits>::memory_space;
464  static_assert(! is_memory_space_specified ||
465  Kokkos::Impl::is_memory_space<memory_space>::value,
466  "Specified memory space is not a Kokkos memory space.");
467  static_assert(is_memory_space_specified ||
468  Kokkos::Impl::is_memory_space<memory_space>::value,
469  "Default memory space is not a Kokkos memory space.");
470 
471  using access_mode = typename traits::access_mode;
472 
488  LocalAccess (global_object_type& G,
489  const execution_space& execSpace,
490  const memory_space& memSpace,
491  const bool viewIsValid = true) :
492  G_ (G),
493  execSpace_ (execSpace),
494  memSpace_ (memSpace),
495  valid_ (viewIsValid)
496  {}
497 
500  LocalAccess (global_object_type& G,
501  const bool viewIsValid = true) :
502  LocalAccess (G,
503  DefaultExecutionSpace<global_object_type>::space (G),
504  DefaultMemorySpace<global_object_type>::space (G),
505  viewIsValid)
506  {}
507 
511  LocalAccess (global_object_type& G,
512  const execution_space& execSpace,
513  const bool viewIsValid = true) :
514  LocalAccess (G,
515  execSpace,
516  DefaultMemorySpace<global_object_type>::space (G),
517  viewIsValid)
518  {}
519 
523  LocalAccess (global_object_type& G,
524  const memory_space& memSpace,
525  const bool viewIsValid = true) :
526  LocalAccess (G,
527  DefaultExecutionSpace<global_object_type>::space (G),
528  memSpace,
529  viewIsValid)
530  {}
531 
539  bool isValid () const { return valid_; }
540 
543  execution_space getExecutionSpace () const { return execSpace_; }
544 
547  memory_space getMemorySpace () const { return memSpace_; }
548 
560  this_type
561  valid (const bool thisIsValid) const {
562  return {G_, getExecutionSpace(), getMemorySpace(),
563  thisIsValid};
564  }
565 
568  template<class NewMemorySpace>
569  typename std::conditional<
570  is_execution_space_specified,
571  LocalAccess<global_object_type, execution_space,
572  NewMemorySpace, access_mode>,
574  >::type
575  on(const NewMemorySpace& memSpace) const {
576  using Kokkos::Impl::is_memory_space;
577  static_assert(is_memory_space<NewMemorySpace>::value,
578  "NewMemorySpace must be a Kokkos memory space.");
579 
580  // We can't use std::conditional here, because we need the
581  // "select" method.
582  using alt_execution_space =
583  typename LocalAccess<global_object_type, NewMemorySpace,
584  access_mode>::execution_space;
585  auto execSpace = Kokkos::Impl::if_c<
586  is_execution_space_specified,
587  execution_space,
588  alt_execution_space>::select(
590  alt_execution_space());
591  return {G_, execSpace, memSpace, isValid()};
592  }
593 
596  template<class NewExecutionSpace>
597  typename std::conditional<
598  is_memory_space_specified,
599  LocalAccess<global_object_type, NewExecutionSpace,
600  memory_space, access_mode>,
602  >::type
603  at(const NewExecutionSpace& execSpace) const {
604  using Kokkos::Impl::is_execution_space;
605  static_assert(is_execution_space<NewExecutionSpace>::value,
606  "NewExecutionSpace must be a Kokkos execution space.");
607 
608  // We can't use std::conditional here, because we need the
609  // "select" method.
610  using alt_memory_space =
611  typename LocalAccess<global_object_type, NewExecutionSpace,
612  access_mode>::memory_space;
613  auto memSpace = Kokkos::Impl::if_c<
614  is_memory_space_specified,
615  memory_space,
616  alt_memory_space>::select(
617  getMemorySpace(),
618  alt_memory_space());
619  return {G_, execSpace, memSpace, isValid()};
620  }
621 
622  public:
628  global_object_type& G_;
629 
635  execution_space execSpace_;
636 
642  memory_space memSpace_;
643 
645  bool valid_;
646  };
647  } // namespace Details
648 
650  // Implementations of readOnly, writeOnly, and readWrite
652 
653  template<class GlobalObjectType>
655  GlobalObjectType,
656  Access::ReadOnly>
657  readOnly (GlobalObjectType& G)
658  {
659  return {G};
660  }
661 
662  template<class GlobalObjectType>
663  Details::LocalAccess<
664  GlobalObjectType,
665  Access::ReadOnly>
666  readOnly (const GlobalObjectType& G)
667  {
668  GlobalObjectType& G_nc = const_cast<GlobalObjectType&> (G);
669  return {G_nc};
670  }
671 
672  template<class GlobalObjectType>
673  Details::LocalAccess<
674  GlobalObjectType,
675  Access::WriteOnly>
676  writeOnly (GlobalObjectType& G)
677  {
678  return {G};
679  }
680 
681  template<class GlobalObjectType>
682  Details::LocalAccess<
683  GlobalObjectType,
684  Access::ReadWrite>
685  readWrite (GlobalObjectType& G)
686  {
687  return {G};
688  }
689 
691  // Implementation of withLocalAccess
693 
694  namespace Details {
695 
697  // Use std::tuple as a compile-time list (Greenspun's 10th Rule)
699 
700  // cons<T, std::tuple<Args...>>::type is std::tuple<T, Args...>.
701  // This is the usual Lisp CONS function, but for std::tuple. I
702  // got the idea from
703  // https://stackoverflow.com/questions/18701798/building-and-accessing-a-list-of-types-at-compile-time
704  // but without "struct Void {};", and with head of new list
705  // ordered first instead of last (hence "cons").
706  template<class ...> struct cons;
707 
708  // (CONS SomeType NIL)
709  template<class T, template <class ...> class List>
710  struct cons<T, List<>> {
711  using type = List<T>;
712  };
713 
714  // (CONS SomeType ListOfTypes)
715  template <class T, template <class ...> class List, class ...Types>
716  struct cons<T, List<Types...>>
717  {
718  typedef List<T, Types...> type;
719  };
720 
722  // Map from std::tuple<Ts...> to std::function<void (Ts...)>.
724 
725  // I got inspiration from
726  // https://stackoverflow.com/questions/15418841/how-do-i-strip-a-tuple-back-into-a-variadic-template-list-of-types
727  //
728  // The only significant change was from "using type = T<Ts...>;",
729  // to "using type = std::function<void (Ts...)>;".
730  template<class T>
731  struct tuple_to_function_type { };
732 
733  template<typename... Ts>
734  struct tuple_to_function_type<std::tuple<Ts...> >
735  {
736  using type = std::function<void (Ts...)>;
737  };
738 
739  // Map from a list of zero or more LocalAccess types, to the
740  // corresponding list of arguments for the user function to give to
741  // withLocalAccess.
742  template<class ... Args>
743  struct ArgsToFunction {};
744 
745  template<>
746  struct ArgsToFunction<> {
747  using arg_list_type = std::tuple<>;
748 
749  // Implementers should only use this.
750  using type = std::function<void ()>;
751  };
752 
753  template<class FirstLocalAccessType, class ... Rest>
754  struct ArgsToFunction<FirstLocalAccessType, Rest...> {
755  using head_arg_type =
756  with_local_access_function_argument_type<FirstLocalAccessType>;
757  using tail_arg_list_type =
758  typename ArgsToFunction<Rest...>::arg_list_type;
759  using arg_list_type =
760  typename cons<head_arg_type, tail_arg_list_type>::type;
761 
762  // Implementers should only use this.
763  using type = typename tuple_to_function_type<arg_list_type>::type;
764  };
765 
770  template<class ... LocalAccessTypes>
772  using current_user_function_type =
773  typename ArgsToFunction<LocalAccessTypes...>::type;
774 
775  static void
776  withLocalAccess (LocalAccessTypes...,
777  typename ArgsToFunction<LocalAccessTypes...>::type);
778  };
779 
783  template<>
784  struct WithLocalAccess<> {
785  using current_user_function_type =
786  typename ArgsToFunction<>::type;
787 
788  static void
789  withLocalAccess (current_user_function_type userFunction)
790  {
791  userFunction ();
792  }
793  };
794 
799  template<class FirstLocalAccessType>
800  struct WithLocalAccess<FirstLocalAccessType> {
801  using current_user_function_type =
802  typename ArgsToFunction<FirstLocalAccessType>::type;
803 
804  static void
805  withLocalAccess (current_user_function_type userFunction,
806  FirstLocalAccessType first)
807  {
808  // The "master" local object is the scope guard for local
809  // data. Its constructor may allocate temporary storage, copy
810  // data to the desired memory space, etc. Its destructor will
811  // put everything back. "Put everything back" could be a
812  // no-op, or it could copy data back so where they need to go
813  // and/or free temporary storage.
814  //
815  // Users define this function and the type it returns by
816  // specializing GetMasterLocalObject for LocalAccess
817  // specializations.
818  auto first_lcl_master = getMasterLocalObject (first);
819 
820  // The "nonowning" local object is a nonowning view of the
821  // "master" local object. This is the only local object that
822  // users see, and they see it as input to their function.
823  // Subsequent slices / subviews view this nonowning local
824  // object. All such nonowning views must have lifetime
825  // contained within the lifetime of the master local object.
826  //
827  // Users define this function and the type it returns by
828  // specializing GetNonowningLocalObject (see above).
829  //
830  // Constraining the nonowning views' lifetime to this scope
831  // means that master local object types may use low-cost
832  // ownership models, like that of std::unique_ptr. There
833  // should be no need for reference counting (in the manner of
834  // std::shared_ptr) or Herb Sutter's deferred_heap.
835  auto first_lcl_view = getNonowningLocalObject (first, first_lcl_master);
836 
837  // Curry the user's function by fixing the first argument.
838 
840  ([=] () {
841  userFunction (first_lcl_view);
842  });
843  }
844  };
845 
852  template<class FirstLocalAccessType, class ... Rest>
853  struct WithLocalAccess<FirstLocalAccessType, Rest...> {
854  using current_user_function_type =
855  typename ArgsToFunction<FirstLocalAccessType, Rest...>::type;
856 
857  static void
858  withLocalAccess (current_user_function_type userFunction,
859  FirstLocalAccessType first,
860  Rest... rest)
861  {
862  // The "master" local object is the scope guard for local
863  // data. Its constructor may allocate temporary storage, copy
864  // data to the desired memory space, etc. Its destructor will
865  // put everything back. "Put everything back" could be a
866  // no-op, or it could copy data back so where they need to go
867  // and/or free temporary storage.
868  //
869  // Users define this function and the type it returns by
870  // specializing GetMasterLocalObject for LocalAccess
871  // specializations.
872  auto first_lcl_master = getMasterLocalObject (first);
873 
874  // The "nonowning" local object is a nonowning view of the
875  // "master" local object. This is the only local object that
876  // users see, and they see it as input to their function.
877  // Subsequent slices / subviews view this nonowning local
878  // object. All such nonowning views must have lifetime
879  // contained within the lifetime of the master local object.
880  //
881  // Users define this function and the type it returns by
882  // specializing GetNonowningLocalObject (see above).
883  //
884  // Constraining the nonowning views' lifetime to this scope
885  // means that master local object types may use low-cost
886  // ownership models, like that of std::unique_ptr. There
887  // should be no need for reference counting (in the manner of
888  // std::shared_ptr) or Herb Sutter's deferred_heap.
889  auto first_lcl_view = getNonowningLocalObject (first, first_lcl_master);
890 
891  // Curry the user's function by fixing the first argument.
892 
895  userFunction (first_lcl_view, args...);
896  },
897  rest...);
898  }
899  };
900  } // namespace Details
901 
903  // withLocalAccess function declaration and definition
905 
938  template<class ... LocalAccessTypes>
939  void
941  (typename Details::ArgsToFunction<LocalAccessTypes...>::type userFunction,
942  LocalAccessTypes... localAccesses)
943  {
944  using impl_type = Details::WithLocalAccess<LocalAccessTypes...>;
945  impl_type::withLocalAccess (userFunction, localAccesses...);
946  }
947 
948 } // namespace Tpetra
949 
950 #endif // TPETRA_WITHLOCALACCESS_HPP
Mapping from &quot;master&quot; local object type to the nonowning &quot;local view&quot; type that users see (as argumen...
bool valid_
Will I actually need to access this object?
memory_space getMemorySpace() const
Memory space instance, on which the user will access local data.
Declaration of access intent for a global object.
LocalAccess(global_object_type &G, const bool viewIsValid=true)
Constructor that specifies the global object and (optionally) whether it is valid.
global_object_type & G_
Reference to the global object whose data the user will access.
Details::LocalAccess< GlobalObjectType, Access::WriteOnly > writeOnly(GlobalObjectType &)
Declare that you want to access the given global object&#39;s local data in write-only mode...
Details::LocalAccess< GlobalObjectType, Access::ReadWrite > readWrite(GlobalObjectType &)
Declare that you want to access the given global object&#39;s local data in read-and-write mode...
this_type valid(const bool thisIsValid) const
Declare at run time whether you actually want to access the object.
std::conditional< is_memory_space_specified, LocalAccess< global_object_type, NewExecutionSpace, memory_space, access_mode >, LocalAccess< global_object_type, NewExecutionSpace, access_mode > >::type at(const NewExecutionSpace &execSpace) const
Declare intent to access this object&#39;s local data at a specific (Kokkos) execution space (instance)...
LocalAccess(global_object_type &G, const execution_space &execSpace, const memory_space &memSpace, const bool viewIsValid=true)
Constructor that specifies the global object, the execution memory space instance on which to view it...
GetNonowningLocalObject< LocalAccessType >::nonowning_local_object_type getNonowningLocalObject(LocalAccessType LA, const typename GetMasterLocalObject< LocalAccessType >::master_local_object_type &master)
Given a master local object, get an instance of a nonowning local object.
Implementation of withLocalAccess.
LocalAccess(global_object_type &G, const execution_space &execSpace, const bool viewIsValid=true)
Constructor that specifies the global object, the execution space instance at which to view its local...
execution_space execSpace_
Execution space instance, with which the user will access local data.
GetMasterLocalObject< LocalAccessType >::master_local_object_type getMasterLocalObject(LocalAccessType LA)
Given a LocalAccess instance (which has a reference to a global object), get an instance of its maste...
Deduce types from parameter pack of LocalAccess.
void withLocalAccess(typename Details::ArgsToFunction< LocalAccessTypes...>::type userFunction, LocalAccessTypes...localAccesses)
Get access to a Tpetra global object&#39;s local data.
Tag indicating an unspecified type in LocalAccessTraits.
LocalAccess(global_object_type &G, const memory_space &memSpace, const bool viewIsValid=true)
Constructor that specifies the global object, the memory space instance on which to view its local da...
memory_space memSpace_
Memory space instance, on which the user will access local data.
Details::LocalAccess< GlobalObjectType, Access::ReadOnly > readOnly(GlobalObjectType &)
Declare that you want to access the given global object&#39;s local data in read-only mode...
Given a global object, get its default execution space (both the type and the default instance thereo...
bool isValid() const
Is access supposed to be valid?
std::conditional< is_execution_space_specified, LocalAccess< global_object_type, execution_space, NewMemorySpace, access_mode >, LocalAccess< global_object_type, NewMemorySpace, access_mode > >::type on(const NewMemorySpace &memSpace) const
Declare intent to access this object&#39;s local data on a specific (Kokkos) memory space (instance)...
typename Details::GetNonowningLocalObject< LocalAccessType >::nonowning_local_object_type with_local_access_function_argument_type
Type of the local object, that is an argument to the function the user gives to withLocalAccess.
Given a global object, get its default memory space (both the type and the default instance thereof)...
Mapping from LocalAccess to the &quot;master&quot; local object type.
execution_space getExecutionSpace() const
Execution space instance, at which the user will access local data.