3#include <AMReX_Config.H>
38template <
typename T, std::
integral N>
39T
Sum (N n, T
const* v, T init_val = 0);
57template <
typename T, std::
integral N,
typename F>
58requires (!std::same_as<T*,std::decay_t<F>>)
59T
Sum (N n,
F const& f, T init_val = 0);
75template <
typename T, std::
integral N>
76T
Min (N n, T
const* v, T init_val = std::numeric_limits<T>::max());
94template <
typename T, std::
integral N,
typename F>
95requires (!std::same_as<T*,std::decay_t<F>>)
96T
Min (N n,
F const& f, T init_val = std::numeric_limits<T>::max());
112template <
typename T, std::
integral N>
113T
Max (N n, T
const* v, T init_val = std::numeric_limits<T>::lowest());
131template <
typename T, std::
integral N,
typename F>
132requires (!std::same_as<T*,std::decay_t<F>>)
133T
Max (N n,
F const& f, T init_val = std::numeric_limits<T>::lowest());
148template <
typename T, std::
integral N>
149std::pair<T,T>
MinMax (N n, T
const* v);
166template <
typename T, std::
integral N,
typename F>
167requires (!std::same_as<T*,std::decay_t<F>>)
168std::pair<T,T>
MinMax (N n,
F const& f);
185template <
typename T, std::
integral N,
typename P>
186bool AnyOf (N n, T
const* v, P
const& pred);
201template <
typename P,
int dim>
207namespace Reduce::detail {
211 template <std::
size_t I,
typename T,
typename P>
213 void for_each_parallel (T& d, T
const& s,
Gpu::Handler const& h)
215 P().parallel_update(amrex::get<I>(d), amrex::get<I>(s), h);
218 template <std::size_t I,
typename T,
typename P,
typename P1,
typename... Ps>
220 void for_each_parallel (T& d, T
const& s, Gpu::Handler
const& h)
222 P().parallel_update(amrex::get<I>(d), amrex::get<I>(s), h);
223 for_each_parallel<I+1,T,P1,Ps...>(d, s, h);
226 template <std::
size_t I,
typename T,
typename P>
228 void for_each_parallel (T& d, T
const& s)
230 P().parallel_update(amrex::get<I>(d), amrex::get<I>(s));
233 template <std::size_t I,
typename T,
typename P,
typename P1,
typename... Ps>
235 void for_each_parallel (T& d, T
const& s)
237 P().parallel_update(amrex::get<I>(d), amrex::get<I>(s));
238 for_each_parallel<I+1,T,P1,Ps...>(d, s);
243 template <std::
size_t I,
typename T,
typename P>
245 void for_each_local (T& d, T
const& s)
247 P().local_update(amrex::get<I>(d), amrex::get<I>(s));
250 template <std::size_t I,
typename T,
typename P,
typename P1,
typename... Ps>
252 void for_each_local (T& d, T
const& s)
254 P().local_update(amrex::get<I>(d), amrex::get<I>(s));
255 for_each_local<I+1,T,P1,Ps...>(d, s);
258 template <std::
size_t I,
typename T,
typename P>
260 constexpr void for_each_init (T& t)
262 P().init(amrex::get<I>(t));
265 template <std::size_t I,
typename T,
typename P,
typename P1,
typename... Ps>
267 constexpr void for_each_init (T& t)
269 P().init(amrex::get<I>(t));
270 for_each_init<I+1,T,P1,Ps...>(t);
281 template <
typename T>
285 if (h.threadIdx() == 0) { d += r; }
288 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
291 T r = Gpu::blockReduceSum<MT>(s);
292 if (threadIdx.x == 0) { d += r; }
297 template <
typename T>
301 template <
typename T>
302 constexpr void init (T& t)
const noexcept { t = 0; }
310 template <
typename T>
314 if (h.threadIdx() == 0) { d =
amrex::min(d,r); }
317 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
320 T r = Gpu::blockReduceMin<MT>(s);
321 if (threadIdx.x == 0) { d =
amrex::min(d,r); }
326 template <
typename T>
330 template <
typename T>
331 requires (std::numeric_limits<T>::is_specialized)
332 constexpr void init (T& t)
const noexcept { t = std::numeric_limits<T>::max(); }
334 template <
typename T>
335 requires (!std::numeric_limits<T>::is_specialized)
336 constexpr void init (T& t)
const noexcept { t = T::max(); }
344 template <
typename T>
348 if (h.threadIdx() == 0) { d =
amrex::max(d,r); }
351 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
354 T r = Gpu::blockReduceMax<MT>(s);
355 if (threadIdx.x == 0) { d =
amrex::max(d,r); }
360 template <
typename T>
364 template <
typename T>
365 requires (std::numeric_limits<T>::is_specialized)
366 constexpr void init (T& t)
const noexcept { t = std::numeric_limits<T>::lowest(); }
368 template <
typename T>
369 requires (!std::numeric_limits<T>::is_specialized)
370 constexpr void init (T& t)
const noexcept { t = T::lowest(); }
378 template <std::
integral T>
382 if (h.threadIdx() == 0) { d = d && r; }
385 template <std::
integral T,
int MT=AMREX_GPU_MAX_THREADS>
388 T r = Gpu::blockReduceLogicalAnd<MT>(s);
389 if (threadIdx.x == 0) { d = d && r; }
394 template <std::
integral T>
398 template <std::
integral T>
399 constexpr void init (T& t)
const noexcept { t =
true; }
407 template <std::
integral T>
411 if (h.threadIdx() == 0) { d = d || r; }
414 template <std::
integral T,
int MT=AMREX_GPU_MAX_THREADS>
417 T r = Gpu::blockReduceLogicalOr<MT>(s);
418 if (threadIdx.x == 0) { d = d || r; }
423 template <std::
integral T>
427 template <std::
integral T>
428 constexpr void init (T& t)
const noexcept { t =
false; }
431template <
typename... Ps>
class ReduceOps;
436template <
typename... Ts>
442 template <
typename... Ps>
444 : m_max_blocks(
Gpu::
Device::maxBlocksPerLaunch()),
447 * m_max_blocks * sizeof(
Type)))),
448 m_fn_value([&reduce_op,this] () ->
Type { return this->
value(reduce_op); })
450 reduce_op.resetResultReadiness();
451 static_assert(std::is_trivially_copyable<Type>(),
452 "ReduceData::Type must be trivially copyable");
453 static_assert(std::is_trivially_destructible<Type>(),
454 "ReduceData::Type must be trivially destructible");
456 new (m_host_tuple) Type();
462 !m_used_external_stream || m_value_called,
463 "ReduceData used on an external GPU stream must call value() before destruction.");
475 Type r = m_fn_value();
476 m_value_called =
true;
480 template <
typename... Ps>
484 m_value_called =
true;
490 return m_device_tuple+streamIndexChecked(s)*m_max_blocks;
502 m_max_stream_index = std::max(m_max_stream_index,streamIndexChecked(s));
513 if (m_stream_index_zero_set) {
515 "ReduceData cannot be reused across different external GPU streams "
516 "or between an external GPU stream and AMReX stream 0.");
518 m_stream_index_zero = s;
519 m_stream_index_zero_set =
true;
526 int m_max_stream_index = 0;
527 Type* m_host_tuple =
nullptr;
528 Type* m_device_tuple =
nullptr;
529 GpuArray<int,AMREX_GPU_MAX_STREAMS> m_nblocks;
531 bool m_stream_index_zero_set =
false;
532 bool m_used_external_stream =
false;
533 bool m_value_called =
false;
534 std::function<Type()> m_fn_value;
538namespace Reduce::detail {
542 template <
typename F,
int dim>
544 auto call_f_intvect_box (F
const& f, IntVectND<dim> iv, IndexTypeND<dim>)
noexcept ->
545 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv))
547 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv);
550 template <
typename F,
int dim>
552 auto call_f_intvect_box (F
const& f, IntVectND<dim> iv, IndexTypeND<dim> t)
noexcept ->
553 decltype(f(BoxND<dim>(iv, iv, t)))
555 return f(BoxND<dim>(iv, iv, t));
559 template <
typename F,
typename T,
int dim>
561 auto call_f_intvect_n (F
const& f, IntVectND<dim> iv, T n)
noexcept ->
562 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n))
564 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n);
569 struct iterate_box {};
570 struct iterate_box_comp {};
572 template <
typename I,
typename F,
typename T,
typename... Ps>
573 requires (std::same_as<iterate_box,I>)
575 void mf_call_f (F
const& f,
int ibox,
int i,
int j,
int k,
int, T& r)
noexcept
577 auto const& pr = f(ibox,i,j,k);
578 Reduce::detail::for_each_local<0, T, Ps...>(r, pr);
581 template <
typename I,
typename F,
typename T,
typename... Ps>
582 requires (std::same_as<iterate_box_comp,I>)
584 void mf_call_f (F
const& f,
int ibox,
int i,
int j,
int k,
int ncomp, T& r)
noexcept
586 for (
int n = 0; n < ncomp; ++n) {
587 auto const& pr = f(ibox,i,j,k,n);
588 Reduce::detail::for_each_local<0, T, Ps...>(r, pr);
595template <
typename... Ps>
603 template <
typename I,
typename MF,
typename D,
typename F>
604 void eval_mf (I, MF
const& mf,
IntVect const& nghost,
int ncomp, D& reduce_data,
F const& f)
606 using ReduceTuple =
typename D::Type;
607 const int nboxes = mf.local_size();
609 auto const& parforinfo = mf.getParForInfo(nghost);
610 auto nblocks_per_box = parforinfo.getNBlocksPerBox(AMREX_GPU_MAX_THREADS);
612 const int nblocks = nblocks_per_box * nboxes;
613 const BoxIndexer* dp_boxes = parforinfo.getBoxes();
615 auto const& stream = Gpu::gpuStream();
616 auto pdst = reduce_data.devicePtr(stream);
617 int nblocks_ec = std::min(nblocks, reduce_data.maxBlocks());
619 int& nblocks_ref = reduce_data.nBlocks(stream);
620 auto old_nblocks =
static_cast<unsigned int>(nblocks_ref);
621 nblocks_ref =
amrex::max(nblocks_ref, nblocks_ec);
622 reduce_data.updateMaxStreamIndex(stream);
626 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
627 * std::max(Gpu::Device::warp_size, AMREX_GPU_MAX_THREADS/Gpu::Device::warp_size);
628 amrex::launch<AMREX_GPU_MAX_THREADS>(nblocks_ec, shared_mem_bytes, stream,
631 Dim1 blockIdx {gh.blockIdx()};
632 Dim1 threadIdx{gh.threadIdx()};
634 amrex::launch_global<AMREX_GPU_MAX_THREADS>
635 <<<nblocks_ec, AMREX_GPU_MAX_THREADS, 0, stream>>>
640 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
641 ReduceTuple& dst =
pdst[blockIdx.x];
642 if (threadIdx.x == 0 && blockIdx.x >= old_nblocks) {
645 for (
int iblock = blockIdx.x; iblock < nblocks; iblock += nblocks_ec) {
646 int ibox = iblock / nblocks_per_box;
647 auto icell = std::uint64_t(iblock-ibox*nblocks_per_box)*AMREX_GPU_MAX_THREADS + threadIdx.x;
650 if (icell < indexer.
numPts()) {
651 auto [i, j, k] = indexer(icell);
652 Reduce::detail::mf_call_f<I,
F, ReduceTuple, Ps...>
653 (f, ibox, i, j, k, ncomp, r);
657 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
659 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
666 template <
typename I,
int dim,
typename D,
typename F>
667 void eval_box (I,
BoxND<dim> const& box,
int ncomp, D& reduce_data,
F const& f)
670 using ReduceTuple =
typename D::Type;
671 auto const& stream = Gpu::gpuStream();
672 auto dp = reduce_data.devicePtr(stream);
673 int& nblocks = reduce_data.nBlocks(stream);
676 constexpr int nitems_per_thread = 4;
677 Long nblocks_ec = (box.
numPts() + nitems_per_thread*AMREX_GPU_MAX_THREADS-1)
678 / (nitems_per_thread*AMREX_GPU_MAX_THREADS);
679 nblocks_ec = std::min<Long>(nblocks_ec, reduce_data.maxBlocks());
680 reduce_data.updateMaxStreamIndex(stream);
683 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
684 * std::max(Gpu::Device::warp_size, AMREX_GPU_MAX_THREADS/Gpu::Device::warp_size);
685 amrex::launch<AMREX_GPU_MAX_THREADS>(nblocks_ec, shared_mem_bytes, stream,
688 Dim1 blockIdx {gh.blockIdx()};
689 Dim1 threadIdx{gh.threadIdx()};
690 Dim1 gridDim {gh.gridDim()};
692 amrex::launch<AMREX_GPU_MAX_THREADS>(nblocks_ec, 0, stream,
697 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
698 ReduceTuple& dst = *(dp+blockIdx.x);
699 if (threadIdx.x == 0 &&
static_cast<int>(blockIdx.x) >= nblocks) {
702 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
703 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gridDim.x;
707 auto iv = indexer.
intVect(icell);
709 if constexpr (std::is_same_v<Reduce::detail::iterate_box,I>) {
710 auto pr = Reduce::detail::call_f_intvect_box(f, iv, ixtype);
711 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, pr);
713 for (
int n = 0; n < ncomp; ++n) {
714 auto pr = Reduce::detail::call_f_intvect_n(f, iv, n);
715 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, pr);
720 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
722 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
725 nblocks = std::max(nblocks,
static_cast<int>(nblocks_ec));
730 template <FabArrayType MF,
typename D,
typename F>
731#ifndef AMREX_USE_CUDA
734 void eval (MF
const& mf,
IntVect const& nghost, D& reduce_data, F&& f)
736 using ReduceTuple =
typename D::Type;
737 const int nboxes = mf.local_size();
740 }
else if (!mf.isFusingCandidate()) {
743 const int li = mfi.LocalIndex();
744 this->eval(b, reduce_data,
747 return f(li, i, j, k);
751 eval_mf(Reduce::detail::iterate_box{},
752 mf, nghost, 0, reduce_data, std::forward<F>(f));
756 template <FabArrayType MF,
typename D,
typename F>
757#ifndef AMREX_USE_CUDA
760 void eval (MF
const& mf,
IntVect const& nghost,
int ncomp, D& reduce_data, F&& f)
762 using ReduceTuple =
typename D::Type;
764 const int nboxes = mf.local_size();
768 }
else if (!mf.isFusingCandidate()) {
771 const int li = mfi.LocalIndex();
772 this->eval(b, ncomp, reduce_data,
775 return f(li, i, j, k, n);
779 eval_mf(Reduce::detail::iterate_box_comp{},
780 mf, nghost, ncomp, reduce_data, std::forward<F>(f));
784 template <
typename D,
typename F,
int dim>
787 eval_box(Reduce::detail::iterate_box{}, box, 0, reduce_data, f);
790 template <std::
integral N,
typename D,
typename F,
int dim>
793 eval_box(Reduce::detail::iterate_box_comp{}, box, ncomp, reduce_data, f);
796 template <std::
integral N,
typename D,
typename F>
797 void eval (N n, D & reduce_data, F
const& f)
799 if (n <= 0) {
return; }
800 using ReduceTuple =
typename D::Type;
801 auto const& stream = Gpu::gpuStream();
802 auto dp = reduce_data.devicePtr(stream);
803 int& nblocks = reduce_data.nBlocks(stream);
804 constexpr int nitems_per_thread = 4;
805 Long nblocks_ec_long = (
Long(n) + nitems_per_thread*AMREX_GPU_MAX_THREADS-1)
806 / (nitems_per_thread*AMREX_GPU_MAX_THREADS);
807 int nblocks_ec =
static_cast<int>(std::min<Long>(nblocks_ec_long,
808 reduce_data.maxBlocks()));
809 reduce_data.updateMaxStreamIndex(stream);
812 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
813 * std::max(Gpu::Device::warp_size, AMREX_GPU_MAX_THREADS/Gpu::Device::warp_size);
814 amrex::launch<AMREX_GPU_MAX_THREADS>(nblocks_ec, shared_mem_bytes, stream,
817 Dim1 blockIdx {gh.blockIdx()};
818 Dim1 threadIdx{gh.threadIdx()};
819 Dim1 gridDim {gh.gridDim()};
821 amrex::launch<AMREX_GPU_MAX_THREADS>(nblocks_ec, 0, stream,
826 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
827 ReduceTuple& dst = *(dp+blockIdx.x);
828 if (threadIdx.x == 0 &&
static_cast<int>(blockIdx.x) >= nblocks) {
831 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
832 stride =
Long(AMREX_GPU_MAX_THREADS)*gridDim.x;
837 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r,pr);
840 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
842 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
848 template <
typename D>
849 typename D::Type
value (D & reduce_data)
851 auto hp = reduce_data.hostPtr();
853 if (m_result_is_ready) {
854 reduce_data.markValueCalled();
858 using ReduceTuple =
typename D::Type;
859 auto const& stream = Gpu::gpuStream();
860 auto dp = reduce_data.devicePtr();
861 auto const& nblocks = reduce_data.nBlocks();
862#if defined(AMREX_USE_SYCL)
863 if (reduce_data.maxStreamIndex() == 0 && nblocks[0] <= 4096) {
864 const int N = nblocks[0];
866 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(*hp);
869 Gpu::dtoh_memcpy_async(tmp.
data(), dp,
sizeof(ReduceTuple)*N);
870 Gpu::streamSynchronize();
871 for (
int i = 1; i < N; ++i) {
872 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(tmp[0], tmp[i]);
879 int maxblocks = reduce_data.maxBlocks();
882 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
883 * std::max(Gpu::Device::warp_size, AMREX_GPU_MAX_THREADS/Gpu::Device::warp_size);
884#ifndef AMREX_NO_SYCL_REDUCE_WORKAROUND
887 auto presult = dtmp.
data();
891 amrex::launch<AMREX_GPU_MAX_THREADS>(1, shared_mem_bytes, stream,
895 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
897 for (
int istream = 0, nstreams = nblocks.size(); istream < nstreams; ++istream) {
898 auto dp_stream = dp+istream*maxblocks;
899 for (
int i = gh.item->get_global_id(0), stride = gh.item->get_global_range(0);
900 i < nblocks[istream]; i += stride) {
901 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, dp_stream[i]);
904 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
905 if (gh.threadIdx() == 0) { *presult = dst; }
907#ifndef AMREX_NO_SYCL_REDUCE_WORKAROUND
908 Gpu::dtoh_memcpy_async(hp, dtmp.
data(),
sizeof(ReduceTuple));
911 amrex::launch<AMREX_GPU_MAX_THREADS>(1, 0, stream,
915 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
917 for (
int istream = 0, nstreams = nblocks.size(); istream < nstreams; ++istream) {
918 auto dp_stream = dp+istream*maxblocks;
919 for (
int i = AMREX_GPU_MAX_THREADS*blockIdx.x+threadIdx.x, stride = AMREX_GPU_MAX_THREADS*gridDim.x;
920 i < nblocks[istream]; i += stride) {
921 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, dp_stream[i]);
924 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
925 if (threadIdx.x == 0) { *hp = dst; }
928 Gpu::streamSynchronize();
931 m_result_is_ready =
true;
932 reduce_data.markValueCalled();
938 bool m_result_is_ready =
false;
939 void resetResultReadiness () { m_result_is_ready =
false; }
944template <
typename T, std::
integral N>
945T Sum (N n, T
const* v, T init_val)
949 using ReduceTuple =
typename decltype(reduce_data)::Type;
951 ReduceTuple hv = reduce_data.
value(reduce_op);
952 return amrex::get<0>(hv) + init_val;
955template <
typename T, std::
integral N,
typename F>
956requires (!std::same_as<T*,std::decay_t<F>>)
957T Sum (N n, F
const& f, T init_val)
961 using ReduceTuple =
typename decltype(reduce_data)::Type;
963 ReduceTuple hv = reduce_data.
value(reduce_op);
964 return amrex::get<0>(hv) + init_val;
967template <
typename T, std::
integral N>
968T Min (N n, T
const* v, T init_val)
972 using ReduceTuple =
typename decltype(reduce_data)::Type;
974 ReduceTuple hv = reduce_data.
value(reduce_op);
975 return std::min(amrex::get<0>(hv),init_val);
978template <
typename T, std::
integral N,
typename F>
979requires (!std::same_as<T*,std::decay_t<F>>)
980T Min (N n, F
const& f, T init_val)
984 using ReduceTuple =
typename decltype(reduce_data)::Type;
986 ReduceTuple hv = reduce_data.
value(reduce_op);
987 return std::min(amrex::get<0>(hv),init_val);
990template <
typename T, std::
integral N>
991T Max (N n, T
const* v, T init_val)
995 using ReduceTuple =
typename decltype(reduce_data)::Type;
997 ReduceTuple hv = reduce_data.
value(reduce_op);
998 return std::max(amrex::get<0>(hv),init_val);
1001template <
typename T, std::
integral N,
typename F>
1002requires (!std::same_as<T*,std::decay_t<F>>)
1003T Max (N n, F
const& f, T init_val)
1007 using ReduceTuple =
typename decltype(reduce_data)::Type;
1009 ReduceTuple hv = reduce_data.
value(reduce_op);
1010 return std::max(amrex::get<0>(hv),init_val);
1013template <
typename T, std::
integral N>
1018 using ReduceTuple =
typename decltype(reduce_data)::Type;
1022 auto hv = reduce_data.
value(reduce_op);
1023 return std::make_pair(amrex::get<0>(hv), amrex::get<1>(hv));
1026template <
typename T, std::
integral N,
typename F>
1027requires (!std::same_as<T*,std::decay_t<F>>)
1028std::pair<T,T> MinMax (N n, F
const& f)
1032 using ReduceTuple =
typename decltype(reduce_data)::Type;
1037 auto hv = reduce_data.
value(reduce_op);
1038 return std::make_pair(amrex::get<0>(hv), amrex::get<1>(hv));
1041template <
typename T, std::
integral N,
typename P>
1042bool AnyOf (N n, T
const* v, P
const& pred)
1048 ec.numBlocks.x = std::min(ec.numBlocks.x, Gpu::Device::maxBlocksPerLaunch());
1050#ifdef AMREX_USE_SYCL
1051 const int num_ints = std::max(Gpu::Device::warp_size,
int(ec.numThreads.x)/Gpu::Device::warp_size) + 1;
1052 const std::size_t shared_mem_bytes = num_ints*
sizeof(
int);
1053 amrex::launch<AMREX_GPU_MAX_THREADS>(ec.numBlocks.x, shared_mem_bytes, Gpu::gpuStream(),
1055 int* has_any = &(
static_cast<int*
>(gh.sharedMemory())[num_ints-1]);
1056 if (gh.threadIdx() == 0) { *has_any = *dp; }
1062 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*gh.blockIdx()+gh.threadIdx(),
1063 stride =
Long(AMREX_GPU_MAX_THREADS)*gh.gridDim();
1064 i <
Long(n) && !r; i += stride)
1066 r = pred(v[i]) ? 1 : 0;
1069 r = Gpu::blockReduce<Gpu::Device::warp_size>
1071 if (gh.threadIdx() == 0 && r) { *dp = 1; }
1075 amrex::launch<AMREX_GPU_MAX_THREADS>(ec.numBlocks.x, 0, Gpu::gpuStream(),
1077 __shared__
int has_any;
1078 if (threadIdx.x == 0) { has_any = *dp; }
1084 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
1085 stride =
Long(AMREX_GPU_MAX_THREADS)*gridDim.x;
1086 i <
Long(n) && !r; i += stride)
1088 r = pred(v[i]) ? 1 : 0;
1090 r = Gpu::blockReduce<Gpu::Device::warp_size>
1092 if (threadIdx.x == 0 && r) *dp = 1;
1099template <
typename P,
int dim>
1107 ec.numBlocks.x = std::min(ec.numBlocks.x, Gpu::Device::maxBlocksPerLaunch());
1109#ifdef AMREX_USE_SYCL
1110 const int num_ints = std::max(Gpu::Device::warp_size,
int(ec.numThreads.x)/Gpu::Device::warp_size) + 1;
1111 const std::size_t shared_mem_bytes = num_ints*
sizeof(
int);
1112 amrex::launch<AMREX_GPU_MAX_THREADS>(ec.numBlocks.x, shared_mem_bytes, Gpu::gpuStream(),
1114 int* has_any = &(
static_cast<int*
>(gh.sharedMemory())[num_ints-1]);
1115 if (gh.threadIdx() == 0) { *has_any = *dp; }
1121 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*gh.blockIdx()+gh.threadIdx(),
1122 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gh.gridDim();
1123 icell < indexer.
numPts() && !r;
1126 auto iv = indexer.
intVect(icell);
1127 r = amrex::detail::call_f_intvect(pred, iv) ? 1 : 0;
1129 r = Gpu::blockReduce<Gpu::Device::warp_size>
1131 if (gh.threadIdx() == 0 && r) { *dp = 1; }
1138 __shared__
int has_any;
1139 if (threadIdx.x == 0) { has_any = *dp; }
1145 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
1146 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gridDim.x;
1147 icell < indexer.
numPts() && !r;
1150 auto iv = indexer.
intVect(icell);
1151 r = amrex::detail::call_f_intvect(pred, iv) ? 1 : 0;
1153 r = Gpu::blockReduce<Gpu::Device::warp_size>
1155 if (threadIdx.x == 0 && r) *dp = 1;
1166template <
typename... Ts>
1170 using Type = GpuTuple<Ts...>;
1172 template <
typename... Ps>
1173 explicit ReduceData (ReduceOps<Ps...>& reduce_op)
1174 : m_tuple(OpenMP::in_parallel() ? 1 : OpenMP::get_max_threads()),
1175 m_fn_value([&reduce_op,this] () -> Type { return this->value(reduce_op); })
1177 reduce_op.resetResultReadiness();
1178 for (
auto& t : m_tuple) {
1179 Reduce::detail::for_each_init<0, Type, Ps...>(t);
1183 ~ReduceData () =
default;
1184 ReduceData (ReduceData<Ts...>
const&) =
delete;
1185 ReduceData (ReduceData<Ts...> &&) =
delete;
1186 void operator= (ReduceData<Ts...>
const&) =
delete;
1187 void operator= (ReduceData<Ts...> &&) =
delete;
1189 Type value () {
return m_fn_value(); }
1191 template <
typename... Ps>
1192 Type value (ReduceOps<Ps...>& reduce_op)
1194 return reduce_op.value(*
this);
1197 Vector<Type>& reference () {
return m_tuple; }
1199 Type& reference (
int tid)
1201 if (m_tuple.size() == 1) {
1205 return m_tuple[tid];
1210 Vector<Type> m_tuple;
1211 std::function<Type()> m_fn_value;
1214namespace Reduce::detail {
1218 template <
typename F,
int dim>
1220 auto call_f_intvect (F
const& f, IntVectND<dim> iv)
noexcept ->
1221 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv))
1223 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv);
1228 template <
typename F,
typename T,
int dim>
1230 auto call_f_intvect_n (F
const& f, IntVectND<dim> iv, T n)
noexcept ->
1231 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n))
1233 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n);
1237template <
typename... Ps>
1244 template <
typename D,
typename F,
int dim>
1245 requires (std::same_as<std::decay_t<
decltype(
1246 Reduce::detail::call_f_intvect(std::declval<F const&>(), IntVectND<dim>()))>,
1249 static void call_f_box (BoxND<dim>
const& box,
typename D::Type & r, F
const& f)
noexcept
1251 using ReduceTuple =
typename D::Type;
1253 [&] (IntVectND<dim> iv) {
1254 auto pr = Reduce::detail::call_f_intvect(f, iv);
1255 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, pr);
1259 template <
typename D,
typename F,
int dim>
1260 requires (std::same_as<std::decay_t<
decltype(
1261 std::declval<F const&>()(std::declval<BoxND<dim>
const&>()))>,
1264 static void call_f_box (BoxND<dim>
const& box,
typename D::Type & r, F
const& f)
noexcept
1266 using ReduceTuple =
typename D::Type;
1267 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, f(box));
1272 template <FabArrayType MF,
typename D,
typename F>
1273 requires (IsCallable<F, int, int, int, int>::value)
1274 void eval (MF
const& mf, IntVect
const& nghost, D & reduce_data, F
const& f)
1276 using ReduceTuple =
typename D::Type;
1282 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1283 for (MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1284 Box const& b = mfi.growntilebox(nghost);
1285 const int li = mfi.LocalIndex();
1288 for (
int k = lo.z; k <= hi.z; ++k) {
1289 for (
int j = lo.y; j <= hi.y; ++j) {
1290 for (
int i = lo.x; i <= hi.x; ++i) {
1291 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, f(li,i,j,k));
1294 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1295 reduce_data.reference(OpenMP::get_thread_num()), rr);
1299 template <FabArrayType MF,
typename D,
typename F>
1300 requires (IsCallable<F, int, int, int, int, int>::value)
1301 void eval (MF
const& mf, IntVect
const& nghost,
int ncomp, D & reduce_data, F
const& f)
1303 using ReduceTuple =
typename D::Type;
1309 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1310 for (MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1311 Box const& b = mfi.growntilebox(nghost);
1312 const int li = mfi.LocalIndex();
1315 for (
int n = 0; n < ncomp; ++n) {
1316 for (
int k = lo.z; k <= hi.z; ++k) {
1317 for (
int j = lo.y; j <= hi.y; ++j) {
1318 for (
int i = lo.x; i <= hi.x; ++i) {
1319 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, f(li,i,j,k,n));
1322 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1323 reduce_data.reference(OpenMP::get_thread_num()), rr);
1327 template <
typename D,
typename F,
int dim>
1328 void eval (BoxND<dim>
const& box, D & reduce_data, F&& f)
1330 using ReduceTuple =
typename D::Type;
1332 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1333 call_f_box<D>(box, rr, std::forward<F>(f));
1334 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1335 reduce_data.reference(OpenMP::get_thread_num()), rr);
1338 template <std::
integral N,
typename D,
typename F,
int dim>
1339 void eval (BoxND<dim>
const& box, N ncomp, D & reduce_data, F
const& f)
1341 using ReduceTuple =
typename D::Type;
1343 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1345 [&] (IntVectND<dim> iv,
int n) {
1346 auto pr = Reduce::detail::call_f_intvect_n(f, iv, n);
1347 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, pr);
1349 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1350 reduce_data.reference(OpenMP::get_thread_num()), rr);
1353 template <std::
integral N,
typename D,
typename F>
1354 void eval (N n, D & reduce_data, F
const& f)
1356 using ReduceTuple =
typename D::Type;
1358 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1359 for (N i = 0; i < n; ++i) {
1360 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, f(i));
1362 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1363 reduce_data.reference(OpenMP::get_thread_num()), rr);
1366 template <
typename D>
1367 typename D::Type value (D & reduce_data)
1369 auto& rrv = reduce_data.reference();
1370 if (! m_result_is_ready) {
1371 using ReduceTuple =
typename D::Type;
1372 if (rrv.size() > 1) {
1373 for (
int i = 1, N = rrv.size(); i < N; ++i) {
1374 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rrv[0], rrv[i]);
1377 m_result_is_ready =
true;
1383 template <
typename... T>
friend class ReduceData;
1384 bool m_result_is_ready =
false;
1385 void resetResultReadiness () { m_result_is_ready =
false; }
1390template <
typename T, std::
integral N,
typename F>
1391requires (!std::same_as<T*,std::decay_t<F>>)
1392T Sum (N n, F
const& f, T init_val)
1396#pragma omp parallel for reduction(+:r)
1398 for (N i = 0; i < n; ++i) {
1404template <
typename T, std::
integral N>
1405T
Sum (N n, T
const* v, T init_val)
1407 return Sum(n, [=] (N i) -> T {
return v[i]; }, init_val);
1410template <
typename T, std::
integral N,
typename F>
1411requires (!std::same_as<T*,std::decay_t<F>>)
1412T Min (N n, F
const& f, T init_val)
1416#pragma omp parallel for reduction(min:r)
1418 for (N i = 0; i < n; ++i) {
1419 r = std::min(r,f(i));
1424template <
typename T, std::
integral N>
1425T
Min (N n, T
const* v, T init_val)
1427 return Reduce::Min(n, [=] (N i) -> T {
return v[i]; }, init_val);
1430template <
typename T, std::
integral N,
typename F>
1431requires (!std::same_as<T*,std::decay_t<F>>)
1432T Max (N n, F
const& f, T init_val)
1436#pragma omp parallel for reduction(max:r)
1438 for (N i = 0; i < n; ++i) {
1439 r = std::max(r,f(i));
1444template <
typename T, std::
integral N>
1445T
Max (N n, T
const* v, T init_val)
1447 return Reduce::Max(n, [=] (N i) -> T {
return v[i]; }, init_val);
1450template <
typename T, std::
integral N,
typename F>
1451requires (!std::same_as<T*,std::decay_t<F>>)
1452std::pair<T,T> MinMax (N n, F
const& f)
1454 T r_min = std::numeric_limits<T>::max();
1455 T r_max = std::numeric_limits<T>::lowest();
1457#pragma omp parallel for reduction(min:r_min) reduction(max:r_max)
1459 for (N i = 0; i < n; ++i) {
1461 r_min = std::min(r_min,tmp);
1462 r_max = std::max(r_max,tmp);
1464 return std::make_pair(r_min,r_max);
1467template <
typename T, std::
integral N>
1468std::pair<T,T>
MinMax (N n, T
const* v)
1470 return Reduce::MinMax<T>(n, [=] (N i) -> T {
return v[i]; });
1473template <
typename T, std::
integral N,
typename P>
1474bool AnyOf (N n, T
const* v, P
const& pred)
1476 return std::any_of(v, v+n, pred);
1479template <
typename P,
int dim>
1480bool AnyOf (BoxND<dim>
const& box, P
const& pred)
1482 for (
auto iv : box.iterator()) {
1483 if (Reduce::detail::call_f_intvect(pred, iv)) {
return true; }
1496template <
typename... Ts,
typename... Ps>
1498constexpr GpuTuple<Ts...>
1502 Reduce::detail::for_each_init<0,
decltype(r), Ps...>(r);
1510template <
typename... Ts,
typename... Ps>
1512constexpr GpuTuple<Ts...>
1516 Reduce::detail::for_each_init<0,
decltype(r), Ps...>(r);
1521template <
typename Ops,
typename Ts>
1524template <
typename... Ops,
typename... Ts>
1525class ReducerImpl<TypeList<Ops...>, TypeList<Ts...>>
1528 static_assert(
sizeof...(Ops) > 0);
1529 static_assert(
sizeof...(Ts) > 0);
1530 static_assert(
sizeof...(Ops) ==
sizeof...(Ts));
1533 : m_reduce_data(m_reduce_op)
1537 using Result_t = GpuTuple<Ts...>;
1538 ReduceOps<Ops...> m_reduce_op;
1539 ReduceData<Ts...> m_reduce_data;
1607template <
typename Ops,
typename Ts>
1609 :
public ReducerImpl<ToTypeList_t<Ops>, ToTypeList_t<Ts>>
1623 void operator= (
Reducer const&) =
delete;
1624 void operator= (
Reducer &&) =
delete;
1640 template <
typename F,
int dim>
1645 this->m_reduce_op.
eval(box, this->m_reduce_data, std::forward<F>(f));
1663 template <
typename F,
int dim>
1668 this->m_reduce_op.eval(box, ncomp, this->m_reduce_data, std::forward<F>(f));
1690 template <FabArrayType MF,
typename F>
1692 void eval (MF
const& mf,
IntVect const& nghost, F && f)
1694 this->m_reduce_op.eval(mf, nghost, this->m_reduce_data, std::forward<F>(f));
1719 template <FabArrayType MF,
typename F>
1721 void eval (MF
const& mf,
IntVect const& nghost,
int ncomp, F && f)
1723 this->m_reduce_op.eval(mf, nghost, ncomp, this->m_reduce_data, std::forward<F>(f));
1738 template <
typename N,
typename F>
1740 void eval (N n, F && f)
1742 this->m_reduce_op.eval(n, this->m_reduce_data, std::forward<F>(f));
1757 return this->m_reduce_data.value(this->m_reduce_op);
Memory arena base class and global arena accessors.
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#define AMREX_GPU_MAX_STREAMS
Definition AMReX_GpuDevice.H:21
#define AMREX_LAUNCH_KERNEL(MT, blocks, threads, sharedMem, stream,...)
Definition AMReX_GpuLaunch.H:37
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_GPU_HOST_DEVICE
Definition AMReX_GpuQualifiers.H:20
Convenience header for the core AMReX GPU facilities.
Real * pdst
Definition AMReX_HypreMLABecLap.cpp:1132
virtual void free(void *pt)=0
Free a previously allocated block pointed to by pt.
A Rectangular Domain on an Integer Lattice.
Definition AMReX_Box.H:54
__host__ __device__ bool isEmpty() const noexcept
Checks if it is an empty BoxND.
Definition AMReX_Box.H:223
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:385
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:148
GPU-compatible tuple.
Definition AMReX_Tuple.H:104
static int streamIndex(gpuStream_t s=gpuStream()) noexcept
Definition AMReX_GpuDevice.cpp:715
static bool usingExternalStream() noexcept
Definition AMReX_GpuDevice.cpp:842
Cell-Based or Node-Based Indices.
Definition AMReX_IndexType.H:36
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:176
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
T * data() noexcept
Definition AMReX_PODVector.H:672
Definition AMReX_Reduce.H:438
~ReduceData()
Definition AMReX_Reduce.H:460
int maxStreamIndex() const
Definition AMReX_Reduce.H:500
Type value()
Definition AMReX_Reduce.H:473
void updateMaxStreamIndex(gpuStream_t const &s)
Definition AMReX_Reduce.H:501
int & nBlocks(gpuStream_t const &s)
Definition AMReX_Reduce.H:496
ReduceData(ReduceOps< Ps... > &reduce_op)
Definition AMReX_Reduce.H:443
void markValueCalled() noexcept
Definition AMReX_Reduce.H:505
Type * devicePtr(gpuStream_t const &s)
Definition AMReX_Reduce.H:489
Type value(ReduceOps< Ps... > &reduce_op)
Definition AMReX_Reduce.H:481
Type * devicePtr()
Definition AMReX_Reduce.H:488
GpuArray< int, 8 > & nBlocks()
Definition AMReX_Reduce.H:495
ReduceData(ReduceData< Ts... > const &)=delete
Type * hostPtr()
Definition AMReX_Reduce.H:493
int maxBlocks() const
Definition AMReX_Reduce.H:498
ReduceData(ReduceData< Ts... > &&)=delete
Definition AMReX_Reduce.H:597
void eval(BoxND< dim > const &box, N ncomp, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:791
D::Type value(D &reduce_data)
Definition AMReX_Reduce.H:849
void eval(BoxND< dim > const &box, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:785
void eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:734
void eval(N n, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:797
Class for local reductions (e.g., sum, min and max).
Definition AMReX_Reduce.H:1610
Result_t getResult()
Get the final reduction result.
Definition AMReX_Reduce.H:1755
typename Base::Result_t Result_t
Reduction result type, GpuTuple<U...>, where U... are the types in Ts.
Definition AMReX_Reduce.H:1614
void eval(BoxND< dim > const &box, F &&f)
Reduction over a Box.
Definition AMReX_Reduce.H:1643
amrex_long Long
Definition AMReX_INT.H:30
T Min(N n, T const *v, T init_val=std::numeric_limits< T >::max())
Compute the minimum of an array of values.
Definition AMReX_Reduce.H:968
bool AnyOf(N n, T const *v, P const &pred)
Test whether any element in an array satisfies a unary predicate.
Definition AMReX_Reduce.H:1042
std::pair< T, T > MinMax(N n, T const *v)
Compute the minimum and maximum of an array of values.
Definition AMReX_Reduce.H:1014
T Max(N n, T const *v, T init_val=std::numeric_limits< T >::lowest())
Compute the maximum of an array of values.
Definition AMReX_Reduce.H:991
T Sum(N n, T const *v, T init_val=0)
Compute the sum of an array of values.
Definition AMReX_Reduce.H:945
__host__ __device__ Dim3 ubound(Array4< T > const &a) noexcept
Return the inclusive upper bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1365
__host__ __device__ Dim3 lbound(Array4< T > const &a) noexcept
Return the inclusive lower bounds of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1351
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Return a copy of b grown uniformly by i cells in every direction.
Definition AMReX_Box.H:1326
Arena * The_Pinned_Arena()
Definition AMReX_Arena.cpp:855
Arena * The_Arena()
Definition AMReX_Arena.cpp:815
void Sum(Gpu::DeviceVector< T > &v, MPI_Comm comm)
Definition AMReX_GpuParallelReduce.H:37
__host__ __device__ constexpr const T & min(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:31
__host__ __device__ constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:53
__host__ __device__ AMREX_FORCE_INLINE T Max(T *const m, T const value) noexcept
Definition AMReX_GpuAtomic.H:419
__host__ __device__ AMREX_FORCE_INLINE T Min(T *const m, T const value) noexcept
Definition AMReX_GpuAtomic.H:356
__device__ int blockReduceLogicalOr(int source) noexcept
Definition AMReX_GpuReduce.H:559
__device__ T blockReduceMax(T source) noexcept
Definition AMReX_GpuReduce.H:458
__device__ T blockReduceMin(T source) noexcept
Definition AMReX_GpuReduce.H:403
__device__ int blockReduceLogicalAnd(int source) noexcept
Definition AMReX_GpuReduce.H:511
__device__ T blockReduceSum(T source) noexcept
Definition AMReX_GpuReduce.H:353
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:259
void For(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:400
cudaStream_t gpuStream_t
Definition AMReX_GpuControl.H:79
__host__ __device__ constexpr GpuTuple< Ts... > IdentityTuple(GpuTuple< Ts... >, ReduceOps< Ps... >) noexcept
Return a GpuTuple containing the identity element for each operation in ReduceOps....
Definition AMReX_Reduce.H:1499
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
typename ToTypeList< T >::type ToTypeList_t
Definition AMReX_TypeList.H:233
const int[]
Definition AMReX_BLProfiler.cpp:1665
Utility that maps flattened point indices back to IntVectND coordinates.
Definition AMReX_Box.H:2494
__host__ __device__ IntVectND< dim > intVect(std::uint64_t icell) const
Convert flattened point index icell to its IntVectND coordinate.
Definition AMReX_Box.H:2517
__host__ __device__ std::uint64_t numPts() const
Return the number of points covered by the indexed box.
Definition AMReX_Box.H:2552
Fixed-size array that can be used on GPU.
Definition AMReX_Array.H:52
Definition AMReX_Tuple.H:133
Definition AMReX_GpuMemory.H:57
T * dataPtr()
Definition AMReX_GpuMemory.H:91
T dataValue() const
Definition AMReX_GpuMemory.H:93
Definition AMReX_GpuLaunch.H:121
Definition AMReX_GpuTypes.H:88
Definition AMReX_GpuControl.H:127
Definition AMReX_GpuReduce.H:290
Test if a given type T is callable with arguments of type Args...
Definition AMReX_TypeTraits.H:208
Function object that returns the sum of two values.
Definition AMReX_Functional.H:23
Definition AMReX_Reduce.H:375
__host__ __device__ void local_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:396
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:399
__device__ void parallel_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:387
Definition AMReX_Reduce.H:404
__device__ void parallel_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:416
__host__ __device__ void local_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:425
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:428
Definition AMReX_Reduce.H:341
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:366
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:362
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:353
Definition AMReX_Reduce.H:307
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:332
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:319
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:328
Definition AMReX_Reduce.H:277
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:290
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:299
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:302
Struct for holding types.
Definition AMReX_TypeList.H:13