RAJA
RAJA provides a collection of platform portability abstractions for C++ HPC applications.
Lambda.hpp
Go to the documentation of this file.
1 
11 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
12 // Copyright (c) Lawrence Livermore National Security, LLC and other
13 // RAJA Project Developers. See top-level LICENSE and COPYRIGHT
14 // files for dates and other details. No copyright assignment is required
15 // to contribute to RAJA.
16 //
17 // SPDX-License-Identifier: (BSD-3-Clause)
18 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
19 
20 #ifndef RAJA_pattern_kernel_Lambda_HPP
21 #define RAJA_pattern_kernel_Lambda_HPP
22 
23 #include "RAJA/config.hpp"
24 
25 #include <iostream>
26 #include <type_traits>
27 
28 #include "camp/camp.hpp"
29 #include "camp/concepts.hpp"
30 #include "camp/tuple.hpp"
31 
32 #include "RAJA/util/macros.hpp"
33 #include "RAJA/util/types.hpp"
34 
37 
38 namespace RAJA
39 {
40 
41 namespace internal
42 {
44 {};
45 
47 {};
48 
50 {};
51 
52 template<typename T>
54 {
55  using type = T;
56 };
57 
58 template<typename T, camp::idx_t V>
59 struct LambdaArg
60 {
61  static constexpr camp::idx_t value = V;
62 };
63 
64 } // namespace internal
65 
70 template<camp::idx_t... args>
71 using Segs =
72  camp::list<internal::LambdaArg<internal::lambda_arg_seg_t, args>...>;
73 
84 template<camp::idx_t... args>
85 using Offsets =
86  camp::list<internal::LambdaArg<internal::lambda_arg_offset_t, args>...>;
87 
88 
93 template<camp::idx_t... args>
94 using Params =
95  camp::list<internal::LambdaArg<internal::lambda_arg_param_t, args>...>;
96 
110 template<typename T, camp::idx_t... values>
111 using ValuesT =
112  camp::list<internal::LambdaArg<internal::lambda_arg_value_t<T>, values>...>;
113 
114 namespace statement
115 {
126 template<camp::idx_t BodyIdx, typename... Args>
127 struct Lambda : internal::Statement<camp::nil>
128 {
129  static const camp::idx_t loop_body_index = BodyIdx;
130 };
131 
132 } // end namespace statement
133 
134 namespace internal
135 {
136 
137 
138 /*
139  * Helper that extracts a segment value for a lambda argument
140  *
141  * By default we use the Span and offset in LoopData to construct the
142  * value.
143  *
144  * This class allows specialization on the segment type in LoopTypes so that
145  * fancier constructions can happen (ie vector_exec, etc.)
146  */
147 template<typename SegmentType, camp::idx_t id>
149 {
150 
151  static_assert(
152  !std::is_same<SegmentType, void>::value,
153  "Segment not assigned, but used in Lambda with Segs<> argument");
154 
155  template<typename Data>
156  RAJA_HOST_DEVICE RAJA_INLINE constexpr static SegmentType extract(Data&& data)
157  {
158  return SegmentType(camp::get<id>(data.segment_tuple)
159  .begin()[camp::get<id>(data.offset_tuple)]);
160  }
161 };
162 
163 /*
164  * Helper that extracts a segment value for a lambda argument
165  *
166  * By default we use the Span and offset in LoopData to construct the
167  * value.
168  *
169  * This class allows specialization on the segment type in LoopTypes so that
170  * fancier constructions can happen (ie vector_exec, etc.)
171  */
172 template<typename OffsetType, camp::idx_t id>
174 {
175 
176  static_assert(
177  !std::is_same<OffsetType, void>::value,
178  "Segment not assigned, but used in Lambda with Offsets<> argument");
179 
180  template<typename Data>
181  RAJA_HOST_DEVICE RAJA_INLINE constexpr static OffsetType extract(Data&& data)
182  {
183  return OffsetType(camp::get<id>(data.offset_tuple));
184  }
185 };
186 
187 
188 /*
189  * Helper that provides first level of argument extraction
190  * This acts as a switchboard between Segs, Offsets, and Params
191  *
192  * It calls LambdaArgExtractor to perform the actual argument extraction.
193  * This allows LambdaArgExtractor to be specialized
194  */
195 template<typename Types, typename T>
197 
198 template<typename Types, camp::idx_t id>
200 {
201 
202  using OffsetType = camp::at_v<typename Types::offset_types_t, id>;
203 
204  static_assert(
205  !std::is_same<OffsetType, void>::value,
206  "Offset not assigned, but used in Lambda with Offsets<> argument");
207 
208  template<typename Data>
209  RAJA_HOST_DEVICE RAJA_INLINE constexpr static OffsetType extract(Data&& data)
210  {
212  std::forward<Data>(data));
213  }
214 };
215 
216 template<typename Types, camp::idx_t id>
218 {
219 
220  using SegmentType = camp::at_v<typename Types::segment_types_t, id>;
221 
222  static_assert(
223  !std::is_same<SegmentType, void>::value,
224  "Segment not assigned, but used in Lambda with Segs<> argument");
225 
226  template<typename Data>
227  RAJA_HOST_DEVICE RAJA_INLINE constexpr static SegmentType extract(Data&& data)
228  {
230  std::forward<Data>(data));
231  }
232 };
233 
234 template<typename Types, camp::idx_t id>
236 {
237  template<typename Data>
238  RAJA_HOST_DEVICE RAJA_INLINE constexpr static auto extract(Data&& data)
239  -> std::add_lvalue_reference_t<
240  camp::tuple_element_t<id, typename camp::decay<Data>::arg_tuple_t>>
241  {
242  return RAJA::expt::detail::get_lambda_arg(camp::get<id>(data.param_tuple));
243  }
244 };
245 
246 template<typename Types, typename T, camp::idx_t value>
248 {
249  template<typename Data>
250  RAJA_HOST_DEVICE RAJA_INLINE constexpr static T extract(Data&&)
251  {
252  return T(value);
253  }
254 };
255 
257 template<camp::idx_t LoopIndex,
258  typename Types,
259  typename Data,
260  typename... targLists>
262  Data&& data,
263  camp::list<targLists...> const&)
264 {
265  camp::get<LoopIndex>(data.bodies)(
267 }
268 
273 template<camp::idx_t LambdaIndex, typename... Args, typename Types>
274 struct StatementExecutor<statement::Lambda<LambdaIndex, Args...>, Types>
275 {
276 
277  template<typename Data>
278  static RAJA_INLINE RAJA_HOST_DEVICE void exec(Data&& data)
279  {
280 
281  // Convert SegList, ParamList into Seg, Param types, and store in a list
282  using targList = typename camp::flatten<camp::list<Args...>>::type;
283 
284  invoke_lambda_with_args<LambdaIndex, Types>(std::forward<Data>(data),
285  targList {});
286  }
287 };
288 
289 template<camp::idx_t LambdaIndex,
290  typename Types,
291  typename Data,
292  camp::idx_t... SEGS,
293  camp::idx_t... PARAMS>
294 RAJA_INLINE RAJA_HOST_DEVICE void invoke_lambda(Data&& data,
295  camp::idx_seq<SEGS...> const&,
296  camp::idx_seq<PARAMS...> const&)
297 {
298 
299  using AllSegs = Segs<SEGS...>;
300  using AllParams = Params<PARAMS...>;
301 
302  // invoke the expanded Lambda executor, passing in all segments and params
304  Types>::exec(std::forward<Data>(data));
305 }
306 
307 template<camp::idx_t LambdaIndex, typename Types>
308 struct StatementExecutor<statement::Lambda<LambdaIndex>, Types>
309 {
310 
311  template<typename Data>
312  static RAJA_INLINE RAJA_HOST_DEVICE void exec(Data&& data)
313  {
314 
315  using Data_t = camp::decay<Data>;
316  using offset_tuple_t = typename Data_t::offset_tuple_t;
317  using param_tuple_t = typename Data_t::param_tuple_t;
318 
319  invoke_lambda<LambdaIndex, Types>(
320  std::forward<Data>(data),
321  camp::make_idx_seq_t<camp::tuple_size<offset_tuple_t>::value> {},
322  camp::make_idx_seq_t<camp::tuple_size<param_tuple_t>::value> {});
323  }
324 };
325 
326 
327 } // namespace internal
328 
329 } // end namespace RAJA
330 
331 
332 #endif /* RAJA_pattern_kernel_HPP */
Header file for common RAJA internal macro definitions.
#define RAJA_HOST_DEVICE
Definition: macros.hpp:65
#define RAJA_SUPPRESS_HD_WARN
Definition: macros.hpp:68
Args args
Definition: WorkRunner.hpp:212
RAJA_HOST_DEVICE std::enable_if_t< std::is_base_of< ParamBase, T >::value, std::add_lvalue_reference_t< typename T::ARG_T > > get_lambda_arg(T &Param)
Definition: params_base.hpp:314
RAJA_INLINE RAJA_HOST_DEVICE void invoke_lambda(Data &&data, camp::idx_seq< SEGS... > const &, camp::idx_seq< PARAMS... > const &)
Definition: Lambda.hpp:294
RAJA_SUPPRESS_HD_WARN RAJA_INLINE RAJA_HOST_DEVICE void invoke_lambda_with_args(Data &&data, camp::list< targLists... > const &)
Definition: Lambda.hpp:261
Definition: AlignedRangeIndexSetBuilders.cpp:35
camp::list< internal::LambdaArg< internal::lambda_arg_value_t< T >, values >... > ValuesT
Definition: Lambda.hpp:112
camp::list< internal::LambdaArg< internal::lambda_arg_param_t, args >... > Params
Definition: Lambda.hpp:95
camp::list< internal::LambdaArg< internal::lambda_arg_offset_t, args >... > Offsets
Definition: Lambda.hpp:86
camp::list< internal::LambdaArg< internal::lambda_arg_seg_t, args >... > Segs
Definition: Lambda.hpp:72
Header file for loop kernel internals.
RAJA_HOST_DEVICE constexpr static RAJA_INLINE OffsetType extract(Data &&data)
Definition: Lambda.hpp:209
camp::at_v< typename Types::offset_types_t, id > OffsetType
Definition: Lambda.hpp:202
RAJA_HOST_DEVICE constexpr static RAJA_INLINE auto extract(Data &&data) -> std::add_lvalue_reference_t< camp::tuple_element_t< id, typename camp::decay< Data >::arg_tuple_t >>
Definition: Lambda.hpp:238
RAJA_HOST_DEVICE constexpr static RAJA_INLINE SegmentType extract(Data &&data)
Definition: Lambda.hpp:227
camp::at_v< typename Types::segment_types_t, id > SegmentType
Definition: Lambda.hpp:220
RAJA_HOST_DEVICE constexpr static RAJA_INLINE T extract(Data &&)
Definition: Lambda.hpp:250
Definition: Lambda.hpp:196
Definition: Lambda.hpp:60
static constexpr camp::idx_t value
Definition: Lambda.hpp:61
Definition: Lambda.hpp:174
RAJA_HOST_DEVICE constexpr static RAJA_INLINE OffsetType extract(Data &&data)
Definition: Lambda.hpp:181
Definition: Lambda.hpp:149
RAJA_HOST_DEVICE constexpr static RAJA_INLINE SegmentType extract(Data &&data)
Definition: Lambda.hpp:156
static RAJA_INLINE RAJA_HOST_DEVICE void exec(Data &&data)
Definition: Lambda.hpp:278
static RAJA_INLINE RAJA_HOST_DEVICE void exec(Data &&data)
Definition: Lambda.hpp:312
Definition: Statement.hpp:48
Definition: Statement.hpp:35
Definition: Lambda.hpp:50
Definition: Lambda.hpp:47
Definition: Lambda.hpp:44
Definition: Lambda.hpp:54
T type
Definition: Lambda.hpp:55
Definition: Lambda.hpp:128
static const camp::idx_t loop_body_index
Definition: Lambda.hpp:129
Header file for RAJA type definitions.