/home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/kokkos.hh Source File#

DiFfRG: /home/runner/work/DiFfRG_current/DiFfRG_current/DiFfRG/include/DiFfRG/common/kokkos.hh Source File
DiFfRG
Discretization Framework for functional Renormalization Group flows
kokkos.hh
Go to the documentation of this file.
1#pragma once
2
4#include <Kokkos_Core.hpp>
5#include <algorithm>
6#include <array>
7#include <type_traits>
8#include <vector>
9
10#ifdef KOKKOS_ENABLE_CUDA
11#include <cuda/std/array>
12#include <cuda/std/tuple>
13#include <cuda/std/utility>
14#else
15#include <array>
16#include <tuple>
17#include <utility>
18#endif
19
20namespace DiFfRG
21{
35 using memory_space = Kokkos::DefaultHostExecutionSpace::memory_space;
36 void fence() const {}
37 };
38
40 {
41 public:
42 using GPU_exec_space = Kokkos::DefaultExecutionSpace;
43 using GPU_memory_space = GPU_exec_space::memory_space;
44
45 using KokkosHost_exec_space = Kokkos::DefaultHostExecutionSpace;
46 using KokkosHost_memory_space = KokkosHost_exec_space::memory_space;
47
50 };
51
55
56 using CPU_memory = Kokkos::DefaultHostExecutionSpace::memory_space;
57
66#ifdef KOKKOS_ENABLE_CUDA
67 using PinnedHost_memory = Kokkos::CudaHostPinnedSpace;
68#else
70#endif
71
75
76 // Ensure that CPU memory space is the same as the Kokkos host and TBB memory spaces.
77 // We assume that this is true, and when switching to a different memory space, it is always unique.
78 static_assert(std::is_same_v<CPU_memory, KokkosHost_memory>,
79 "CPU memory space must be the same as the Kokkos host memory space");
80 static_assert(std::is_same_v<CPU_memory, TBB_memory>, "CPU memory space must be the same as TBB memory space");
81
88 template <class Scalar, class SavedScalar, class Space> struct SumPlus {
89 public:
90 // Required
92 using value_type = std::remove_cv_t<Scalar>;
93 using saved_type = std::remove_cv_t<SavedScalar>;
94 static_assert(!std::is_pointer_v<value_type> && !std::is_array_v<value_type>);
95
96 using result_view_type = Kokkos::View<value_type, Space>;
97
98 private:
101
103
104 public:
105 KOKKOS_INLINE_FUNCTION
106 SumPlus(value_type &value_, const saved_type &plus_value_)
107 : value(&value_), references_scalar_v(true), plus_value(plus_value_)
108 {
109 }
110
111 KOKKOS_INLINE_FUNCTION
112 SumPlus(const result_view_type &value_, const saved_type &plus_value_)
113 : value(value_), references_scalar_v(false), plus_value(plus_value_)
114 {
115 }
116
117 // Required
118 KOKKOS_INLINE_FUNCTION
119 void join(value_type &dest, const value_type &src) const { dest += src; }
120
121 KOKKOS_INLINE_FUNCTION
122 void init(value_type &val) const { val = Kokkos::reduction_identity<value_type>::sum(); }
123
124 KOKKOS_INLINE_FUNCTION
125 value_type &reference() const { return *value.data(); }
126
127 KOKKOS_INLINE_FUNCTION
128 result_view_type view() const { return value; }
129
130 KOKKOS_INLINE_FUNCTION
131 bool references_scalar() const { return references_scalar_v; }
132
133 KOKKOS_INLINE_FUNCTION
134 void final(value_type &update) const { update += plus_value; }
135 };
136
137 namespace device
138 {
139#ifdef KOKKOS_ENABLE_CUDA
140 template <typename... T> using tuple = cuda::std::tuple<T...>;
141 template <typename T, std::size_t N> using array = cuda::std::array<T, N>;
142 using cuda::std::apply;
143 using cuda::std::forward;
144 using cuda::std::forward_as_tuple;
145 using cuda::std::get;
146 using cuda::std::index_sequence;
147 using cuda::std::integer_sequence;
148 using cuda::std::make_integer_sequence;
149 using cuda::std::make_tuple;
150 using cuda::std::tie;
151 using cuda::std::tuple_cat;
152 using cuda::std::tuple_element;
153#else
154 template <typename... T> using tuple = std::tuple<T...>;
155 template <typename T, std::size_t N> using array = std::array<T, N>;
156 using std::apply;
157 using std::forward;
158 using std::forward_as_tuple;
159 using std::get;
160 using std::index_sequence;
161 using std::integer_sequence;
162 using std::make_integer_sequence;
163 using std::make_tuple;
164 using std::tie;
165 using std::tuple_cat;
166 using std::tuple_element;
167#endif
168 } // namespace device
169
170 template <int dim, typename T> struct GetKokkosNDStarType {
171 using type = typename GetKokkosNDStarType<dim - 1, T>::type *;
172 };
173 template <typename T> struct GetKokkosNDStarType<1, T> {
174 using type = T *;
175 };
176
177 // ------------------------------------------------
178 // Getting View types
179 // ------------------------------------------------
180
181 template <int dim, typename T, typename ExecutionSpace>
182 using KokkosNDView = Kokkos::View<typename GetKokkosNDStarType<dim, T>::type, // Get the star syntax for
183 // dimensionality recursively with
184 ExecutionSpace // Choice between GPU and CPU
185 >;
186 template <int dim, typename T, typename ExecutionSpace>
188 Kokkos::View<typename GetKokkosNDStarType<dim, T>::type, // Get the star syntax for dimensionality recursively
189 // with a helper
190 ExecutionSpace, // Choice between GPU and CPU
191 Kokkos::MemoryTraits<Kokkos::Restrict> // No-alias hint for compiler optimization
192 >;
193
194 template <int dim, typename T, typename ExecutionSpace>
196 Kokkos::View<typename GetKokkosNDStarType<dim, T>::type, // Get the star syntax for dimensionality recursively
197 // with a helper
198 ExecutionSpace, // Choice between GPU and CPU
199 Kokkos::MemoryTraits<Kokkos::Unmanaged> // No allocation: Attach to existing memory
200 >;
201
202 template <int dim, typename T, typename ExecutionSpace>
203 auto make_kokkos_nd_view(const std::string &label, const device::array<size_t, dim> &extents)
204 {
205 return device::apply([&](const auto &...args) { return KokkosNDView<dim, T, ExecutionSpace>(label, args...); },
206 extents);
207 }
208
209 template <int dim, typename T, typename ExecutionSpace>
210 auto make_kokkos_nd_view_restrict(const std::string &label, const device::array<size_t, dim> &extents)
211 {
212 return device::apply(
213 [&](const auto &...args) { return KokkosNDViewRestrict<dim, T, ExecutionSpace>(label, args...); }, extents);
214 }
215
216 // ------------------------------------------------
217 // Getting ranges to iterate over
218 // ------------------------------------------------
219 // Pin launch bounds. Without __launch_bounds__ ptxas cannot see the block size and pins registers
220 // differently; measured ~3-14% slower across the YangMills flow set on sm_89, results identical
221 // (numtracer/gpubench/FINDINGS.md). Override with -DDIFFRG_LAUNCH_BOUNDS=N.
222#ifndef DIFFRG_LAUNCH_BOUNDS
223#define DIFFRG_LAUNCH_BOUNDS 128
224#endif
225#if DIFFRG_LAUNCH_BOUNDS == 0 // A/B control: no launch bounds at all (the historical behaviour)
226 template <int dim, typename ExecutionSpace> struct KokkosNDRangeHelper {
227 using type = Kokkos::MDRangePolicy<Kokkos::Rank<dim>, ExecutionSpace>;
228 };
229 template <typename ExecutionSpace> struct KokkosNDRangeHelper<1, ExecutionSpace> {
230 using type = Kokkos::RangePolicy<ExecutionSpace>;
231 };
232#else
233 template <int dim, typename ExecutionSpace> struct KokkosNDRangeHelper {
234 using type = Kokkos::MDRangePolicy<Kokkos::Rank<dim>, ExecutionSpace,
235 Kokkos::LaunchBounds<DIFFRG_LAUNCH_BOUNDS>>;
236 };
237 template <typename ExecutionSpace> struct KokkosNDRangeHelper<1, ExecutionSpace> {
238 using type = Kokkos::RangePolicy<ExecutionSpace, Kokkos::LaunchBounds<DIFFRG_LAUNCH_BOUNDS>>;
239 };
240#endif
241 template <int dim, typename ExecutionSpace> using KokkosNDRange = KokkosNDRangeHelper<dim, ExecutionSpace>::type;
242
243 // Use a tile whose every dimension DIVIDES its extent, instead of Kokkos' heuristic.
244 //
245 // Kokkos picks a tile by halving its recommended tile until the product fits under
246 // min(512, LaunchBounds::maxTperB) -- so every tile dimension it can produce is the recommendation
247 // divided by a power of two. When an extent is not a multiple of that, the boundary tile launches
248 // masked-off lanes that occupy warp slots and do no work.
249 //
250 // That is not hypothetical here. Every QCD_Nf2 model uses angular order 6, and the shipped
251 // LB=128 gives tile {16,2,4,1,1} on the rank-5 flows: extent 6 against tile 4 is ceil(6/4)=2 tiles
252 // covering 8 slots, i.e. 4/3 of the threads launched for 1 unit of work. Since dim0 x dim1 = 32 is
253 // exactly one warp, the masked lanes form whole dead warps. Measured masked fractions at LB=128
254 // (numtracer/gpubench/tools/tilewaste.py): vacuum no_mesons 1.255x, with_mesons 1.306x,
255 // with_mesons_3D 1.299x, finite_T no_mesons 1.314x -- and YangMills 1.000x, because its angular
256 // orders are 8, which the power-of-two tile does divide.
257 //
258 // This is what the A100 LaunchBounds sweep actually measured. LB=96 and LB=64 both collapse the
259 // tile to {16,2,2,1,1}, which divides 6 -- and LB=64 came out 8.0% faster than LB=128 at
260 // *byte-identical* registers (255), spill (1864 B) and occupancy (12.5%), which no occupancy story
261 // explains. Per-flow it splits perfectly: the three rank-5 flows (the only ones with masked lanes)
262 // gained 21.7-24.2% against 25.0% predicted from the masked fraction alone, while every rank-4
263 // flow -- with nothing to recover -- got 0-21.6% *slower* from the smaller block.
264 //
265 // Set -DDIFFRG_DIVISIBLE_TILE=0 to restore Kokkos' heuristic (the A/B control).
266#ifndef DIFFRG_DIVISIBLE_TILE
267#define DIFFRG_DIVISIBLE_TILE 1
268#endif
269
285 template <int dim>
287 const device::array<size_t, dim> &kokkos_tile, size_t budget)
288 {
289 bool already_divides = true;
290 for (int i = 0; i < dim; ++i)
291 if (kokkos_tile[i] == 0 || extents[i] % kokkos_tile[i] != 0) already_divides = false;
292 if (already_divides) return kokkos_tile;
293
294 // Candidate tile values per dimension: the divisors of the extent that fit the budget. Extents
295 // here are quadrature orders and grid sizes (order 10-100), so these lists are short and the
296 // search below visits a few thousand nodes at worst -- negligible against a millisecond kernel.
297 std::array<std::vector<size_t>, dim> candidates;
298 for (int i = 0; i < dim; ++i) {
299 const size_t cap = std::min<size_t>(extents[i], budget);
300 for (size_t d = 1; d <= cap; ++d)
301 if (extents[i] % d == 0) candidates[i].push_back(d);
302 if (candidates[i].empty()) candidates[i].push_back(1); // extent 0: degenerate, launch nothing
303 }
304
305 // Ranking, in order:
306 // (1) whole warps -- a block that is not a multiple of 32 pads its last warp with dead lanes,
307 // which is the very defect being fixed, only at warp instead of tile granularity;
308 // (2) largest block -- fewer blocks, and the register file is handed out per warp;
309 // (3) closest to Kokkos' shape, measured as sum |log2(tile/kokkos)| so the metric is
310 // scale-free: 16->64 costs 2 and 4->2 costs 1, which stops the search from collapsing the
311 // angular dimensions to 1 just to inflate dim 0;
312 // (4) tile weight as far forward as possible, since dim 0 is the contiguous one under
313 // LayoutLeft and a wider dim-0 tile coalesces the cache write better.
314 constexpr size_t warp = 32;
315 const auto log_distance = [&](const device::array<size_t, dim> &tile) {
316 double d = 0.;
317 for (int i = 0; i < dim; ++i)
318 d += std::abs(std::log2(static_cast<double>(tile[i]) / static_cast<double>(kokkos_tile[i])));
319 return d;
320 };
321 const auto lexicographically_greater = [](const device::array<size_t, dim> &a,
323 for (int i = 0; i < dim; ++i)
324 if (a[i] != b[i]) return a[i] > b[i];
325 return false;
326 };
327
328 device::array<size_t, dim> best{}, current{};
329 size_t best_product = 0;
330 double best_distance = 0.;
331 bool best_whole_warps = false, have_best = false;
332
333 const auto visit = [&](auto &&self, int i, size_t product) -> void {
334 if (i == dim) {
335 const bool whole_warps = (product % warp == 0);
336 const double distance = log_distance(current);
337 bool better;
338 if (!have_best)
339 better = true;
340 else if (whole_warps != best_whole_warps)
341 better = whole_warps;
342 else if (product != best_product)
343 better = product > best_product;
344 else if (std::abs(distance - best_distance) > 1e-9)
345 better = distance < best_distance;
346 else
347 better = lexicographically_greater(current, best);
348 if (better) {
349 best = current;
350 best_product = product;
351 best_distance = distance;
352 best_whole_warps = whole_warps;
353 have_best = true;
354 }
355 return;
356 }
357 for (const size_t d : candidates[i]) {
358 if (product * d > budget) break; // candidates are ascending, so nothing further fits either
359 current[i] = d;
360 self(self, i + 1, product * d);
361 }
362 };
363 visit(visit, 0, 1);
364
365 return have_best ? best : kokkos_tile;
366 }
367
372 template <int dim>
374 {
376 for (int i = 0; i < dim; ++i)
377 tile[i] = 1;
378
379 size_t budget = max_threads;
380 // Fill from innermost dimension outward
381 for (int i = dim - 1; i >= 0; --i) {
382 tile[i] = std::min(extents[i], budget);
383 budget /= tile[i];
384 if (budget == 0) break;
385 }
386 return tile;
387 }
388
389 template <int dim, typename ExecutionSpace>
390 auto make_kokkos_nd_range(ExecutionSpace &space, const device::array<size_t, dim> start,
392 {
393 if constexpr (dim == 1) {
394 return KokkosNDRange<dim, ExecutionSpace>(space, start[0], end[0]);
395 } else {
396 Kokkos::Array<size_t, dim> start_view;
397 Kokkos::Array<size_t, dim> end_view;
398 for (size_t i = 0; i < dim; ++i) {
399 start_view[i] = start[i];
400 end_view[i] = end[i];
401 }
402 return KokkosNDRange<dim, ExecutionSpace>(space, start_view, end_view);
403 }
404 }
405
406 template <int dim, typename ExecutionSpace>
407 auto make_kokkos_nd_range(ExecutionSpace &space, const device::array<size_t, dim> start,
409 {
410 if constexpr (dim == 1) {
411 return KokkosNDRange<dim, ExecutionSpace>(space, start[0], end[0]);
412 } else {
413 Kokkos::Array<size_t, dim> start_view;
414 Kokkos::Array<size_t, dim> end_view;
415 Kokkos::Array<size_t, dim> tile_view;
416 for (size_t i = 0; i < dim; ++i) {
417 start_view[i] = start[i];
418 end_view[i] = end[i];
419 tile_view[i] = tile[i];
420 }
421 return KokkosNDRange<dim, ExecutionSpace>(space, start_view, end_view, tile_view);
422 }
423 }
424
436 template <int dim, typename ExecutionSpace>
437 auto make_kokkos_nd_range_divisible(ExecutionSpace &space, const device::array<size_t, dim> start,
439 {
440 auto policy = make_kokkos_nd_range<dim, ExecutionSpace>(space, start, end);
441#if DIFFRG_DIVISIBLE_TILE
442 if constexpr (dim > 1) {
443 device::array<size_t, dim> extents, kokkos_tile;
444 size_t budget = 1;
445 bool changed = false;
446 for (int i = 0; i < dim; ++i) {
447 extents[i] = end[i] - start[i];
448 kokkos_tile[i] = static_cast<size_t>(policy.m_tile[i]);
449 budget *= kokkos_tile[i];
450 }
451 const auto tile = compute_divisible_tile<dim>(extents, kokkos_tile, budget);
452 for (int i = 0; i < dim; ++i)
453 changed |= (tile[i] != kokkos_tile[i]);
454 if (changed) return make_kokkos_nd_range<dim, ExecutionSpace>(space, start, end, tile);
455 }
456#endif
457 return policy;
458 }
459
460 template <int dim, typename TeamType>
461 KOKKOS_FORCEINLINE_FUNCTION auto make_kokkos_nd_thread_range(const TeamType &team, const device::array<size_t, dim> end)
462 {
463 if constexpr (dim == 1) {
464 return Kokkos::TeamThreadRange(team, end[0]);
465 } else {
466 return device::apply([&](const auto &...args) { return Kokkos::TeamThreadMDRange(team, args...); }, end);
467 }
468 }
469
470 // ------------------------------------------------
471 // Wrap Kokkos lambdas
472 // ------------------------------------------------
473
486 template <int dim, typename FUN> struct KokkosNDLambdaWrapper {
487 KOKKOS_FUNCTION
488 KokkosNDLambdaWrapper(const FUN &_fun) : fun(_fun) {};
489
490 template <typename... Args>
491 requires(sizeof...(Args) == dim)
492 KOKKOS_FORCEINLINE_FUNCTION void operator()(Args &&...args) const
493 {
494 fun({{std::forward<Args>(args)...}});
495 }
496
497 FUN fun;
498 };
499
512 template <int dim, typename FUN> struct KokkosNDLambdaWrapperReduction {
513 KOKKOS_FUNCTION
514 KokkosNDLambdaWrapperReduction(const FUN &_fun) : fun(_fun) {};
515
516 template <typename... Args>
517 requires(sizeof...(Args) == dim + 1)
518 KOKKOS_FORCEINLINE_FUNCTION void operator()(Args &&...args) const
519 {
520 impl(device::make_integer_sequence<size_t, dim>{}, device::forward<Args>(args)...);
521 }
522
523 FUN fun;
524
525 private:
526 template <size_t... Is, typename... Args>
527 KOKKOS_FORCEINLINE_FUNCTION void impl(device::integer_sequence<size_t, Is...>, Args &&...args) const
528 {
529 auto tuple = device::tie(args...);
530 fun(device::array<size_t, dim>{{static_cast<size_t>(device::get<Is>(tuple))...}}, device::get<dim>(tuple));
531 }
532 };
533} // namespace DiFfRG
534
535#include <autodiff/forward/real.hpp>
536
537namespace Kokkos
538{ // reduction identity must be defined in Kokkos namespace
539 template <size_t N, class T> struct reduction_identity<autodiff::Real<N, T>> {
540 KOKKOS_FORCEINLINE_FUNCTION static autodiff::Real<N, T> sum() { return autodiff::Real<N, T>(); }
541 };
542} // namespace Kokkos
Definition kokkos.hh:40
TBB_ExecutionSpace TBB_exec_space
Definition kokkos.hh:48
TBB_exec_space::memory_space TBB_memory_space
Definition kokkos.hh:49
Kokkos::DefaultExecutionSpace GPU_exec_space
Definition kokkos.hh:42
Kokkos::DefaultHostExecutionSpace KokkosHost_exec_space
Definition kokkos.hh:45
KokkosHost_exec_space::memory_space KokkosHost_memory_space
Definition kokkos.hh:46
GPU_exec_space::memory_space GPU_memory_space
Definition kokkos.hh:43
std::array< T, N > array
Definition kokkos.hh:155
std::tuple< T... > tuple
Definition kokkos.hh:154
Definition complex_math.hh:10
Kokkos::View< typename GetKokkosNDStarType< dim, T >::type, ExecutionSpace > KokkosNDView
Definition kokkos.hh:182
auto make_kokkos_nd_range(ExecutionSpace &space, const device::array< size_t, dim > start, const device::array< size_t, dim > end)
Definition kokkos.hh:390
auto make_kokkos_nd_range_divisible(ExecutionSpace &space, const device::array< size_t, dim > start, const device::array< size_t, dim > end)
Like make_kokkos_nd_range, but re-tiled so no lane is launched masked.
Definition kokkos.hh:437
device::array< size_t, dim > compute_tile_hints(const device::array< size_t, dim > &extents, size_t max_threads=256)
Compute clamped tile sizes for MDRangePolicy so that the product of tile dimensions does not exceed m...
Definition kokkos.hh:373
Kokkos::View< typename GetKokkosNDStarType< dim, T >::type, ExecutionSpace, Kokkos::MemoryTraits< Kokkos::Unmanaged > > KokkosNDViewUnmanaged
Definition kokkos.hh:195
Kokkos::View< typename GetKokkosNDStarType< dim, T >::type, ExecutionSpace, Kokkos::MemoryTraits< Kokkos::Restrict > > KokkosNDViewRestrict
Definition kokkos.hh:187
CPU_memory PinnedHost_memory
Host memory the device can DMA to/from without staging, i.e. page-locked.
Definition kokkos.hh:69
auto make_kokkos_nd_view_restrict(const std::string &label, const device::array< size_t, dim > &extents)
Definition kokkos.hh:210
device::array< size_t, dim > compute_divisible_tile(const device::array< size_t, dim > &extents, const device::array< size_t, dim > &kokkos_tile, size_t budget)
A tile whose every dimension divides its extent, so no lane is launched masked.
Definition kokkos.hh:286
ExecutionSpaces::KokkosHost_exec_space KokkosHost_exec
Definition kokkos.hh:73
ExecutionSpaces::GPU_exec_space GPU_exec
Definition kokkos.hh:72
Kokkos::DefaultHostExecutionSpace::memory_space CPU_memory
Definition kokkos.hh:56
KOKKOS_FORCEINLINE_FUNCTION auto make_kokkos_nd_thread_range(const TeamType &team, const device::array< size_t, dim > end)
Definition kokkos.hh:461
ExecutionSpaces::KokkosHost_memory_space KokkosHost_memory
Definition kokkos.hh:53
auto make_kokkos_nd_view(const std::string &label, const device::array< size_t, dim > &extents)
Definition kokkos.hh:203
KokkosNDRangeHelper< dim, ExecutionSpace >::type KokkosNDRange
Definition kokkos.hh:241
ExecutionSpaces::GPU_memory_space GPU_memory
Definition kokkos.hh:52
ExecutionSpaces::TBB_memory_space TBB_memory
Definition kokkos.hh:54
Definition kokkos.hh:538
Definition complex_math.hh:19
T * type
Definition kokkos.hh:174
Definition kokkos.hh:170
typename GetKokkosNDStarType< dim - 1, T >::type * type
Definition kokkos.hh:171
This is a functor which wraps a lambda for reduction. Basically, this is necessary when one wants to ...
Definition kokkos.hh:512
KOKKOS_FORCEINLINE_FUNCTION void impl(device::integer_sequence< size_t, Is... >, Args &&...args) const
Definition kokkos.hh:527
FUN fun
Definition kokkos.hh:523
KOKKOS_FUNCTION KokkosNDLambdaWrapperReduction(const FUN &_fun)
Definition kokkos.hh:514
KOKKOS_FORCEINLINE_FUNCTION void operator()(Args &&...args) const
Definition kokkos.hh:518
This is a functor which wraps a lambda. Basically, this is necessary when one wants to call a variadi...
Definition kokkos.hh:486
FUN fun
Definition kokkos.hh:497
KOKKOS_FORCEINLINE_FUNCTION void operator()(Args &&...args) const
Definition kokkos.hh:492
KOKKOS_FUNCTION KokkosNDLambdaWrapper(const FUN &_fun)
Definition kokkos.hh:488
Kokkos::RangePolicy< ExecutionSpace, Kokkos::LaunchBounds< DIFFRG_LAUNCH_BOUNDS > > type
Definition kokkos.hh:238
Definition kokkos.hh:233
Kokkos::MDRangePolicy< Kokkos::Rank< dim >, ExecutionSpace, Kokkos::LaunchBounds< DIFFRG_LAUNCH_BOUNDS > > type
Definition kokkos.hh:234
An extension of the Kokkos::Sum reducer that adds a constant value to the result.
Definition kokkos.hh:88
std::remove_cv_t< SavedScalar > saved_type
Definition kokkos.hh:93
bool references_scalar_v
Definition kokkos.hh:100
KOKKOS_INLINE_FUNCTION SumPlus(value_type &value_, const saved_type &plus_value_)
Definition kokkos.hh:106
KOKKOS_INLINE_FUNCTION bool references_scalar() const
Definition kokkos.hh:131
KOKKOS_INLINE_FUNCTION SumPlus(const result_view_type &value_, const saved_type &plus_value_)
Definition kokkos.hh:112
KOKKOS_INLINE_FUNCTION value_type & reference() const
Definition kokkos.hh:125
Kokkos::View< value_type, Space > result_view_type
Definition kokkos.hh:96
KOKKOS_INLINE_FUNCTION void join(value_type &dest, const value_type &src) const
Definition kokkos.hh:119
KOKKOS_INLINE_FUNCTION void init(value_type &val) const
Definition kokkos.hh:122
result_view_type value
Definition kokkos.hh:99
std::remove_cv_t< Scalar > value_type
Definition kokkos.hh:92
const saved_type plus_value
Definition kokkos.hh:102
KOKKOS_INLINE_FUNCTION result_view_type view() const
Definition kokkos.hh:128
The CPU execution space: TBB, the one host thread pool DiFfRG runs on.
Definition kokkos.hh:34
void fence() const
Definition kokkos.hh:36
Kokkos::DefaultHostExecutionSpace::memory_space memory_space
Definition kokkos.hh:35
static KOKKOS_FORCEINLINE_FUNCTION autodiff::Real< N, T > sum()
Definition kokkos.hh:540