3#include <AMReX_Config.H>
40template <
typename T, std::
integral N>
41T
Sum (N n, T
const* v, T init_val = 0);
59template <
typename T, std::
integral N,
typename F>
60requires (!std::same_as<T*,std::decay_t<F>>)
61T
Sum (N n,
F const& f, T init_val = 0);
77template <
typename T, std::
integral N>
78T
Min (N n, T
const* v, T init_val = std::numeric_limits<T>::max());
96template <
typename T, std::
integral N,
typename F>
97requires (!std::same_as<T*,std::decay_t<F>>)
98T
Min (N n,
F const& f, T init_val = std::numeric_limits<T>::max());
114template <
typename T, std::
integral N>
115T
Max (N n, T
const* v, T init_val = std::numeric_limits<T>::lowest());
133template <
typename T, std::
integral N,
typename F>
134requires (!std::same_as<T*,std::decay_t<F>>)
135T
Max (N n,
F const& f, T init_val = std::numeric_limits<T>::lowest());
150template <
typename T, std::
integral N>
151std::pair<T,T>
MinMax (N n, T
const* v);
168template <
typename T, std::
integral N,
typename F>
169requires (!std::same_as<T*,std::decay_t<F>>)
170std::pair<T,T>
MinMax (N n,
F const& f);
187template <
typename T, std::
integral N,
typename P>
188bool AnyOf (N n, T
const* v, P
const& pred);
203template <
typename P,
int dim>
209namespace Reduce::detail {
213inline constexpr int nacc = 8;
218#if defined(AMREX_CXX_GCC) && !defined(__CUDACC__)
219#define AMREX_PRAGMA_NACC_VECTORIZE _Pragma("GCC unroll 4")
221#define AMREX_PRAGMA_NACC_NOVECTOR _Pragma("GCC novector")
223#define AMREX_PRAGMA_NACC_NOVECTOR
225#define AMREX_PRAGMA_NACC_SCALAR AMREX_PRAGMA_NACC_NOVECTOR _Pragma("GCC unroll 8")
227#define AMREX_PRAGMA_NACC_VECTORIZE
228#define AMREX_PRAGMA_NACC_NOVECTOR
229#define AMREX_PRAGMA_NACC_SCALAR
231static_assert(nacc == 8,
"The AMREX_PRAGMA_NACC unroll factors assume nacc == 8");
234template <std::
integral N>
235std::pair<N,N> chunks_1d (N n)
238 N
const chunk = std::max(
static_cast<N
>(nacc),
static_cast<N
>((n / (4*nthreads) / nacc) * nacc));
239 N
const nchunks = n / chunk + ((n % chunk != 0) ? 1 : 0);
240 return {chunk, nchunks};
245 template <std::
size_t Idx,
typename T,
typename P>
247 void for_each_parallel (T& d, T
const& s, Gpu::Handler
const& h)
252 template <std::size_t Idx,
typename T,
typename P,
typename P1,
typename... Ps>
254 void for_each_parallel (T& d, T
const& s, Gpu::Handler
const& h)
257 for_each_parallel<Idx+1,T,P1,Ps...>(d, s, h);
260 template <std::
size_t Idx,
typename T,
typename P>
262 void for_each_parallel (T& d, T
const& s)
267 template <std::size_t Idx,
typename T,
typename P,
typename P1,
typename... Ps>
269 void for_each_parallel (T& d, T
const& s)
272 for_each_parallel<Idx+1,T,P1,Ps...>(d, s);
277 template <std::
size_t Idx,
typename T,
typename P>
279 void for_each_local (T& d, T
const& s)
284 template <std::size_t Idx,
typename T,
typename P,
typename P1,
typename... Ps>
286 void for_each_local (T& d, T
const& s)
289 for_each_local<Idx+1,T,P1,Ps...>(d, s);
292 template <std::
size_t Idx,
typename T,
typename P>
294 constexpr void for_each_init (T& t)
299 template <std::size_t Idx,
typename T,
typename P,
typename P1,
typename... Ps>
301 constexpr void for_each_init (T& t)
304 for_each_init<Idx+1,T,P1,Ps...>(t);
315 template <
typename T>
319 if (h.threadIdx() == 0) { d += r; }
322 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
326 if (threadIdx.x == 0) { d += r; }
331 template <
typename T>
335 template <
typename T>
336 constexpr void init (T& t)
const noexcept { t = 0; }
344 template <
typename T>
348 if (h.threadIdx() == 0) { d =
amrex::min(d,r); }
351 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
355 if (threadIdx.x == 0) { d =
amrex::min(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>::max(); }
368 template <
typename T>
369 requires (!std::numeric_limits<T>::is_specialized)
370 constexpr void init (T& t)
const noexcept { t = T::max(); }
378 template <
typename T>
382 if (h.threadIdx() == 0) { d =
amrex::max(d,r); }
385 template <
typename T,
int MT=AMREX_GPU_MAX_THREADS>
389 if (threadIdx.x == 0) { d =
amrex::max(d,r); }
394 template <
typename T>
398 template <
typename T>
399 requires (std::numeric_limits<T>::is_specialized)
400 constexpr void init (T& t)
const noexcept { t = std::numeric_limits<T>::lowest(); }
402 template <
typename T>
403 requires (!std::numeric_limits<T>::is_specialized)
404 constexpr void init (T& t)
const noexcept { t = T::lowest(); }
412 template <std::
integral T>
416 if (h.threadIdx() == 0) { d = d && r; }
419 template <std::
integral T,
int MT=AMREX_GPU_MAX_THREADS>
423 if (threadIdx.x == 0) { d = d && r; }
428 template <std::
integral T>
432 template <std::
integral T>
433 constexpr void init (T& t)
const noexcept { t =
true; }
441 template <std::
integral T>
445 if (h.threadIdx() == 0) { d = d || r; }
448 template <std::
integral T,
int MT=AMREX_GPU_MAX_THREADS>
452 if (threadIdx.x == 0) { d = d || r; }
457 template <std::
integral T>
461 template <std::
integral T>
462 constexpr void init (T& t)
const noexcept { t =
false; }
466namespace Reduce::detail {
470template <
typename... Ps>
471inline constexpr bool vectorize_nacc_loop =
472#if defined(AMREX_CXX_GCC) && !defined(__CUDACC__) && (__GNUC__ >= 14) && \
473 (defined(__x86_64__) || defined(__i386__)) && !defined(__SSE4_1__)
474 sizeof...(Ps) != 1 ||
475 !((std::is_same_v<Ps,ReduceOpMin> || std::is_same_v<Ps,ReduceOpMax>) && ...);
483template <
typename Tup>
struct Lanes;
485template <
typename... Ts>
486struct Lanes<GpuTuple<Ts...>>
489 GpuTuple<GpuArray<Ts,nacc>...> data;
490 template <
int K>
auto& get (
int lane)
noexcept {
return amrex::get<K>(data)[lane]; }
491 template <
int K> [[nodiscard]]
auto const&
get (
int lane)
const noexcept {
return amrex::get<K>(data)[lane]; }
493 GpuTuple<Ts...> data[nacc];
494 template <
int K>
auto&
get (
int lane)
noexcept {
return amrex::get<K>(data[lane]); }
495 template <
int K> [[nodiscard]]
auto const&
get (
int lane)
const noexcept {
return amrex::get<K>(data[lane]); }
499template <
int K,
typename Tup>
501void lanes_set (Lanes<Tup>& acc, Tup
const& v)
503 for (
int lane = 0; lane < nacc; ++lane) { acc.template get<K>(lane) =
amrex::get<K>(v); }
504 if constexpr (K+1 < GpuTupleSize<Tup>::value) { lanes_set<K+1>(acc, v); }
507template <
int K,
typename Tup,
typename P,
typename... Ps>
509void lanes_update (Lanes<Tup>& acc,
int lane, Tup
const& s)
511 P().local_update(acc.template get<K>(lane),
amrex::get<K>(s));
512 if constexpr (
sizeof...(Ps) > 0) { lanes_update<K+1,Tup,Ps...>(acc, lane, s); }
515template <
int K,
typename Tup,
typename P,
typename... Ps>
517void lanes_fold (Lanes<Tup>
const& acc, Tup& r)
519 for (
int lane = 0; lane < nacc; ++lane) { P().local_update(
amrex::get<K>(r), acc.template get<K>(lane)); }
520 if constexpr (
sizeof...(Ps) > 0) { lanes_fold<K+1,Tup,Ps...>(acc, r); }
525template <
typename... Ps,
typename Tup, std::integral N,
typename F>
527void reduce_row (N ilo, N ihi, Lanes<Tup>& acc, Tup& rem, F
const& value)
530 AMREX_PRAGMA_NACC_NOVECTOR
531 for (; i + (nacc-1) <= ihi; i += nacc) {
532 if constexpr (vectorize_nacc_loop<Ps...>) {
533 AMREX_PRAGMA_NACC_VECTORIZE
534 for (
int lane = 0; lane < nacc; ++lane) { lanes_update<0,Tup,Ps...>(acc, lane, value(
static_cast<N
>(i+lane))); }
536 AMREX_PRAGMA_NACC_SCALAR
537 for (
int lane = 0; lane < nacc; ++lane) { lanes_update<0,Tup,Ps...>(acc, lane, value(
static_cast<N
>(i+lane))); }
540 AMREX_PRAGMA_NACC_NOVECTOR
541 for (; i <= ihi; ++i) { for_each_local<0,Tup,Ps...>(rem, value(i)); }
544#undef AMREX_PRAGMA_NACC_VECTORIZE
545#undef AMREX_PRAGMA_NACC_NOVECTOR
546#undef AMREX_PRAGMA_NACC_SCALAR
549template <
typename... Ps>
class ReduceOps;
554template <
typename... Ts>
560 template <
typename... Ps>
562 : m_max_blocks(
Gpu::
Device::maxBlocksPerLaunch()),
565 * m_max_blocks * sizeof(
Type)))),
566 m_fn_value([&reduce_op,this] () ->
Type { return this->
value(reduce_op); })
568 reduce_op.resetResultReadiness();
569 static_assert(std::is_trivially_copyable<Type>(),
570 "ReduceData::Type must be trivially copyable");
571 static_assert(std::is_trivially_destructible<Type>(),
572 "ReduceData::Type must be trivially destructible");
574 new (m_host_tuple) Type();
580 !m_used_external_stream || m_value_called,
581 "ReduceData used on an external GPU stream must call value() before destruction.");
593 Type r = m_fn_value();
594 m_value_called =
true;
598 template <
typename... Ps>
602 m_value_called =
true;
608 return m_device_tuple+streamIndexChecked(s)*m_max_blocks;
620 m_max_stream_index = std::max(m_max_stream_index,streamIndexChecked(s));
631 if (m_stream_index_zero_set) {
633 "ReduceData cannot be reused across different external GPU streams "
634 "or between an external GPU stream and AMReX stream 0.");
636 m_stream_index_zero = s;
637 m_stream_index_zero_set =
true;
644 int m_max_stream_index = 0;
645 Type* m_host_tuple =
nullptr;
646 Type* m_device_tuple =
nullptr;
649 bool m_stream_index_zero_set =
false;
650 bool m_used_external_stream =
false;
651 bool m_value_called =
false;
652 std::function<Type()> m_fn_value;
656namespace Reduce::detail {
660 template <
typename F,
int dim>
662 auto call_f_intvect_box (F
const& f, IntVectND<dim> iv, IndexTypeND<dim>)
noexcept ->
663 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv))
665 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv);
668 template <
typename F,
int dim>
670 auto call_f_intvect_box (F
const& f, IntVectND<dim> iv, IndexTypeND<dim> t)
noexcept ->
671 decltype(f(BoxND<dim>(iv, iv, t)))
673 return f(BoxND<dim>(iv, iv, t));
677 template <
typename F,
typename T,
int dim>
679 auto call_f_intvect_n (F
const& f, IntVectND<dim> iv, T n)
noexcept ->
680 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n))
682 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n);
687 struct iterate_box {};
688 struct iterate_box_comp {};
690 template <
typename Tag,
typename F,
typename T,
typename... Ps>
691 requires (std::same_as<iterate_box,Tag>)
693 void mf_call_f (F
const& f,
int ibox,
int i,
int j,
int k,
int, T& r)
noexcept
695 auto const& pr = f(ibox,i,j,k);
696 Reduce::detail::for_each_local<0, T, Ps...>(r, pr);
699 template <
typename Tag,
typename F,
typename T,
typename... Ps>
700 requires (std::same_as<iterate_box_comp,Tag>)
702 void mf_call_f (F
const& f,
int ibox,
int i,
int j,
int k,
int ncomp, T& r)
noexcept
704 for (
int n = 0; n < ncomp; ++n) {
705 auto const& pr = f(ibox,i,j,k,n);
706 Reduce::detail::for_each_local<0, T, Ps...>(r, pr);
713template <
typename... Ps>
721 template <
typename Tag,
typename MF,
typename D,
typename F>
722 void eval_mf (Tag, MF
const& mf,
IntVect const& nghost,
int ncomp, D& reduce_data,
F const& f)
724 using ReduceTuple =
typename D::Type;
725 const int nboxes = mf.local_size();
727 auto const& parforinfo = mf.getParForInfo(nghost);
728 auto nblocks_per_box = parforinfo.getNBlocksPerBox(AMREX_GPU_MAX_THREADS);
730 const int nblocks = nblocks_per_box * nboxes;
731 const BoxIndexer* dp_boxes = parforinfo.getBoxes();
734 auto pdst = reduce_data.devicePtr(stream);
735 int nblocks_ec = std::min(nblocks, reduce_data.maxBlocks());
737 int& nblocks_ref = reduce_data.nBlocks(stream);
738 auto old_nblocks =
static_cast<unsigned int>(nblocks_ref);
739 nblocks_ref =
amrex::max(nblocks_ref, nblocks_ec);
740 reduce_data.updateMaxStreamIndex(stream);
744 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
749 Dim1 blockIdx {gh.blockIdx()};
750 Dim1 threadIdx{gh.threadIdx()};
753 <<<nblocks_ec, AMREX_GPU_MAX_THREADS, 0, stream>>>
758 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
759 ReduceTuple& dst = pdst[blockIdx.x];
760 if (threadIdx.x == 0 && blockIdx.x >= old_nblocks) {
763 for (
int iblock = blockIdx.x; iblock < nblocks; iblock += nblocks_ec) {
764 int ibox = iblock / nblocks_per_box;
765 auto icell = std::uint64_t(iblock-ibox*nblocks_per_box)*AMREX_GPU_MAX_THREADS + threadIdx.x;
768 if (icell < indexer.
numPts()) {
769 auto [i, j, k] = indexer(icell);
770 Reduce::detail::mf_call_f<Tag,
F, ReduceTuple, Ps...>
771 (f, ibox, i, j, k, ncomp, r);
775 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
777 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
784 template <
typename Tag,
int dim,
typename D,
typename F>
785 void eval_box (Tag,
BoxND<dim> const& box,
int ncomp, D& reduce_data,
F const& f)
788 using ReduceTuple =
typename D::Type;
790 auto dp = reduce_data.devicePtr(stream);
791 int& nblocks = reduce_data.nBlocks(stream);
794 constexpr int nitems_per_thread = 4;
795 Long nblocks_ec = (box.
numPts() + nitems_per_thread*AMREX_GPU_MAX_THREADS-1)
796 / (nitems_per_thread*AMREX_GPU_MAX_THREADS);
797 nblocks_ec = std::min<Long>(nblocks_ec, reduce_data.maxBlocks());
798 reduce_data.updateMaxStreamIndex(stream);
801 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
806 Dim1 blockIdx {gh.blockIdx()};
807 Dim1 threadIdx{gh.threadIdx()};
808 Dim1 gridDim {gh.gridDim()};
815 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
816 ReduceTuple& dst = *(dp+blockIdx.x);
817 if (threadIdx.x == 0 &&
static_cast<int>(blockIdx.x) >= nblocks) {
820 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
821 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gridDim.x;
825 auto iv = indexer.
intVect(icell);
827 if constexpr (std::is_same_v<Reduce::detail::iterate_box,Tag>) {
828 auto pr = Reduce::detail::call_f_intvect_box(f, iv, ixtype);
829 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, pr);
831 for (
int n = 0; n < ncomp; ++n) {
832 auto pr = Reduce::detail::call_f_intvect_n(f, iv, n);
833 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, pr);
838 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
840 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
843 nblocks = std::max(nblocks,
static_cast<int>(nblocks_ec));
848 template <FabArrayType MF,
typename D,
typename F>
849#ifndef AMREX_USE_CUDA
852 void eval (MF
const& mf,
IntVect const& nghost, D& reduce_data, F&& f)
854 using ReduceTuple =
typename D::Type;
855 const int nboxes = mf.local_size();
858 }
else if (!mf.isFusingCandidate()) {
861 const int li = mfi.LocalIndex();
862 this->
eval(b, reduce_data,
865 return f(li, i, j, k);
869 eval_mf(Reduce::detail::iterate_box{},
870 mf, nghost, 0, reduce_data, std::forward<F>(f));
874 template <FabArrayType MF,
typename D,
typename F>
875#ifndef AMREX_USE_CUDA
878 void eval (MF
const& mf,
IntVect const& nghost,
int ncomp, D& reduce_data, F&& f)
880 using ReduceTuple =
typename D::Type;
882 const int nboxes = mf.local_size();
886 }
else if (!mf.isFusingCandidate()) {
889 const int li = mfi.LocalIndex();
890 this->
eval(b, ncomp, reduce_data,
893 return f(li, i, j, k, n);
896 }
else if (ncomp == 1) {
898 eval_mf(Reduce::detail::iterate_box{}, mf, nghost, 0, reduce_data,
899 [=]
AMREX_GPU_DEVICE (
int box_no,
int i,
int j,
int k)
noexcept -> ReduceTuple
901 return f(box_no, i, j, k, 0);
904 eval_mf(Reduce::detail::iterate_box_comp{},
905 mf, nghost, ncomp, reduce_data, std::forward<F>(f));
909 template <
typename D,
typename F,
int dim>
912 eval_box(Reduce::detail::iterate_box{}, box, 0, reduce_data, f);
915 template <std::
integral N,
typename D,
typename F,
int dim>
920 eval_box(Reduce::detail::iterate_box{}, box, 0, reduce_data,
923 return Reduce::detail::call_f_intvect_n(f, iv, 0);
926 eval_box(Reduce::detail::iterate_box_comp{}, box, ncomp, reduce_data, f);
930 template <std::
integral N,
typename D,
typename F>
931 void eval (N n, D & reduce_data, F
const& f)
933 if (n <= 0) {
return; }
934 using ReduceTuple =
typename D::Type;
936 auto dp = reduce_data.devicePtr(stream);
937 int& nblocks = reduce_data.nBlocks(stream);
938 constexpr int nitems_per_thread = 4;
939 Long nblocks_ec_long = (
Long(n) + nitems_per_thread*AMREX_GPU_MAX_THREADS-1)
940 / (nitems_per_thread*AMREX_GPU_MAX_THREADS);
941 int nblocks_ec =
static_cast<int>(std::min<Long>(nblocks_ec_long,
942 reduce_data.maxBlocks()));
943 reduce_data.updateMaxStreamIndex(stream);
946 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
951 Dim1 blockIdx {gh.blockIdx()};
952 Dim1 threadIdx{gh.threadIdx()};
953 Dim1 gridDim {gh.gridDim()};
960 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
961 ReduceTuple& dst = *(dp+blockIdx.x);
962 if (threadIdx.x == 0 &&
static_cast<int>(blockIdx.x) >= nblocks) {
965 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
966 stride =
Long(AMREX_GPU_MAX_THREADS)*gridDim.x;
971 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r,pr);
974 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
976 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
982 template <
typename D>
983 typename D::Type
value (D & reduce_data)
985 auto hp = reduce_data.hostPtr();
987 if (m_result_is_ready) {
988 reduce_data.markValueCalled();
992 using ReduceTuple =
typename D::Type;
994 auto dp = reduce_data.devicePtr();
995 auto const& nblocks = reduce_data.nBlocks();
996#if defined(AMREX_USE_SYCL)
997 if (reduce_data.maxStreamIndex() == 0 && nblocks[0] <= 4096) {
998 const int N = nblocks[0];
1000 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(*hp);
1005 for (
int i = 1; i < N; ++i) {
1006 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(tmp[0], tmp[i]);
1013 int maxblocks = reduce_data.maxBlocks();
1014#ifdef AMREX_USE_SYCL
1016 constexpr std::size_t shared_mem_bytes =
sizeof(ReduceTuple)
1018#ifndef AMREX_NO_SYCL_REDUCE_WORKAROUND
1021 auto presult = dtmp.
data();
1029 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
1030 ReduceTuple dst = r;
1031 for (
int istream = 0, nstreams = nblocks.size(); istream < nstreams; ++istream) {
1032 auto dp_stream = dp+istream*maxblocks;
1033 for (
int i = gh.item->get_global_id(0), stride = gh.item->get_global_range(0);
1034 i < nblocks[istream]; i += stride) {
1035 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, dp_stream[i]);
1038 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r, gh);
1039 if (gh.threadIdx() == 0) { *presult = dst; }
1041#ifndef AMREX_NO_SYCL_REDUCE_WORKAROUND
1049 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(r);
1050 ReduceTuple dst = r;
1051 for (
int istream = 0, nstreams = nblocks.size(); istream < nstreams; ++istream) {
1052 auto dp_stream = dp+istream*maxblocks;
1053 for (
int i = AMREX_GPU_MAX_THREADS*blockIdx.x+threadIdx.x, stride = AMREX_GPU_MAX_THREADS*gridDim.x;
1054 i < nblocks[istream]; i += stride) {
1055 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, dp_stream[i]);
1058 Reduce::detail::for_each_parallel<0, ReduceTuple, Ps...>(dst, r);
1059 if (threadIdx.x == 0) { *hp = dst; }
1065 m_result_is_ready =
true;
1066 reduce_data.markValueCalled();
1072 bool m_result_is_ready =
false;
1073 void resetResultReadiness () { m_result_is_ready =
false; }
1078template <
typename T, std::
integral N>
1079T
Sum (N n, T
const* v, T init_val)
1083 using ReduceTuple =
typename decltype(reduce_data)::Type;
1085 ReduceTuple hv = reduce_data.
value(reduce_op);
1089template <
typename T, std::
integral N,
typename F>
1090requires (!std::same_as<T*,std::decay_t<F>>)
1091T
Sum (N n, F
const& f, T init_val)
1095 using ReduceTuple =
typename decltype(reduce_data)::Type;
1097 ReduceTuple hv = reduce_data.
value(reduce_op);
1101template <
typename T, std::
integral N>
1102T
Min (N n, T
const* v, T init_val)
1106 using ReduceTuple =
typename decltype(reduce_data)::Type;
1108 ReduceTuple hv = reduce_data.
value(reduce_op);
1112template <
typename T, std::
integral N,
typename F>
1113requires (!std::same_as<T*,std::decay_t<F>>)
1114T
Min (N n, F
const& f, T init_val)
1118 using ReduceTuple =
typename decltype(reduce_data)::Type;
1120 ReduceTuple hv = reduce_data.
value(reduce_op);
1124template <
typename T, std::
integral N>
1125T
Max (N n, T
const* v, T init_val)
1129 using ReduceTuple =
typename decltype(reduce_data)::Type;
1131 ReduceTuple hv = reduce_data.
value(reduce_op);
1135template <
typename T, std::
integral N,
typename F>
1136requires (!std::same_as<T*,std::decay_t<F>>)
1137T
Max (N n, F
const& f, T init_val)
1141 using ReduceTuple =
typename decltype(reduce_data)::Type;
1143 ReduceTuple hv = reduce_data.
value(reduce_op);
1147template <
typename T, std::
integral N>
1152 using ReduceTuple =
typename decltype(reduce_data)::Type;
1156 auto hv = reduce_data.
value(reduce_op);
1160template <
typename T, std::
integral N,
typename F>
1161requires (!std::same_as<T*,std::decay_t<F>>)
1166 using ReduceTuple =
typename decltype(reduce_data)::Type;
1171 auto hv = reduce_data.
value(reduce_op);
1175template <
typename T, std::
integral N,
typename P>
1176bool AnyOf (N n, T
const* v, P
const& pred)
1184#ifdef AMREX_USE_SYCL
1186 const std::size_t shared_mem_bytes = num_ints*
sizeof(
int);
1189 int* has_any = &(
static_cast<int*
>(gh.sharedMemory())[num_ints-1]);
1190 if (gh.threadIdx() == 0) { *has_any = *dp; }
1196 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*gh.blockIdx()+gh.threadIdx(),
1197 stride =
Long(AMREX_GPU_MAX_THREADS)*gh.gridDim();
1198 i <
Long(n) && !r; i += stride)
1200 r = pred(v[i]) ? 1 : 0;
1205 if (gh.threadIdx() == 0 && r) { *dp = 1; }
1211 __shared__
int has_any;
1212 if (threadIdx.x == 0) { has_any = *dp; }
1218 for (
Long i =
Long(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
1219 stride =
Long(AMREX_GPU_MAX_THREADS)*gridDim.x;
1220 i <
Long(n) && !r; i += stride)
1222 r = pred(v[i]) ? 1 : 0;
1226 if (threadIdx.x == 0 && r) *dp = 1;
1233template <
typename P,
int dim>
1243#ifdef AMREX_USE_SYCL
1245 const std::size_t shared_mem_bytes = num_ints*
sizeof(
int);
1248 int* has_any = &(
static_cast<int*
>(gh.sharedMemory())[num_ints-1]);
1249 if (gh.threadIdx() == 0) { *has_any = *dp; }
1255 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*gh.blockIdx()+gh.threadIdx(),
1256 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gh.gridDim();
1257 icell < indexer.
numPts() && !r;
1260 auto iv = indexer.
intVect(icell);
1261 r = amrex::detail::call_f_intvect(pred, iv) ? 1 : 0;
1265 if (gh.threadIdx() == 0 && r) { *dp = 1; }
1272 __shared__
int has_any;
1273 if (threadIdx.x == 0) { has_any = *dp; }
1279 for (std::uint64_t icell = std::uint64_t(AMREX_GPU_MAX_THREADS)*blockIdx.x+threadIdx.x,
1280 stride = std::uint64_t(AMREX_GPU_MAX_THREADS)*gridDim.x;
1281 icell < indexer.
numPts() && !r;
1284 auto iv = indexer.
intVect(icell);
1285 r = amrex::detail::call_f_intvect(pred, iv) ? 1 : 0;
1289 if (threadIdx.x == 0 && r) *dp = 1;
1300template <
typename... Ts>
1304 using Type = GpuTuple<Ts...>;
1306 template <
typename... Ps>
1307 explicit ReduceData (ReduceOps<Ps...>& reduce_op)
1308 : m_tuple(OpenMP::in_parallel() ? 1 : OpenMP::get_max_threads()),
1309 m_fn_value([&reduce_op,this] () -> Type { return this->value(reduce_op); })
1311 reduce_op.resetResultReadiness();
1312 for (
auto& t : m_tuple) {
1313 Reduce::detail::for_each_init<0, Type, Ps...>(t);
1317 ~ReduceData () =
default;
1318 ReduceData (ReduceData<Ts...>
const&) =
delete;
1319 ReduceData (ReduceData<Ts...> &&) =
delete;
1320 void operator= (ReduceData<Ts...>
const&) =
delete;
1321 void operator= (ReduceData<Ts...> &&) =
delete;
1323 Type value () {
return m_fn_value(); }
1325 template <
typename... Ps>
1326 Type value (ReduceOps<Ps...>& reduce_op)
1328 return reduce_op.value(*
this);
1331 Vector<Type>& reference () {
return m_tuple; }
1333 Type& reference (
int tid)
1335 if (m_tuple.size() == 1) {
1339 return m_tuple[tid];
1344 Vector<Type> m_tuple;
1345 std::function<Type()> m_fn_value;
1348namespace Reduce::detail {
1352 template <
typename F,
int dim>
1354 auto call_f_intvect (F
const& f, IntVectND<dim> iv)
noexcept ->
1355 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv))
1357 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv);
1362 template <
typename F,
typename T,
int dim>
1364 auto call_f_intvect_n (F
const& f, IntVectND<dim> iv, T n)
noexcept ->
1365 decltype(amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n))
1367 return amrex::detail::call_f_intvect_inner(std::make_index_sequence<dim>(), f, iv, n);
1371template <
typename... Ps>
1378 template <
typename D,
typename F,
int dim>
1379 requires (std::same_as<std::decay_t<
decltype(
1380 Reduce::detail::call_f_intvect(std::declval<F const&>(), IntVectND<dim>()))>,
1383 static void call_f_box (BoxND<dim>
const& box,
typename D::Type & r, F
const& f)
noexcept
1385 using ReduceTuple =
typename D::Type;
1387 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rem);
1388 Reduce::detail::Lanes<ReduceTuple> acc;
1389 Reduce::detail::lanes_set<0>(acc, rem);
1390 int const ilo = box.smallEnd(0);
1391 int const ihi = box.bigEnd(0);
1392 BoxND<dim> rows = box;
1393 rows.setBig(0, ilo);
1394 For(rows, [&] (IntVectND<dim> iv) {
1395 Reduce::detail::reduce_row<Ps...>(ilo, ihi, acc, rem, [&] (
int i) {
1397 return Reduce::detail::call_f_intvect(f, iv);
1400 Reduce::detail::lanes_fold<0, ReduceTuple, Ps...>(acc, r);
1401 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, rem);
1404 template <
typename D,
typename F,
int dim>
1405 requires (std::same_as<std::decay_t<
decltype(
1406 std::declval<F const&>()(std::declval<BoxND<dim>
const&>()))>,
1409 static void call_f_box (BoxND<dim>
const& box,
typename D::Type & r, F
const& f)
noexcept
1411 using ReduceTuple =
typename D::Type;
1412 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(r, f(box));
1417 template <FabArrayType MF,
typename D,
typename F>
1418 requires (IsCallable<F, int, int, int, int>::value)
1419 void eval (MF
const& mf, IntVect
const& nghost, D & reduce_data, F
const& f)
1421 using ReduceTuple =
typename D::Type;
1423#pragma omp parallel if (!system::regtest_reduction)
1430 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rem);
1431 Reduce::detail::Lanes<ReduceTuple> acc;
1432 Reduce::detail::lanes_set<0>(acc, rem);
1433 for (MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1434 Box const& b = mfi.growntilebox(nghost);
1435 const int li = mfi.LocalIndex();
1438 for (
int k = lo.z; k <= hi.z; ++k) {
1439 for (
int j = lo.y; j <= hi.y; ++j) {
1440 Reduce::detail::reduce_row<Ps...>(lo.x, hi.x, acc, rem,
1441 [&] (
int i) {
return f(li,i,j,k); });
1444 auto& rr = reduce_data.reference(OpenMP::get_thread_num());
1445 Reduce::detail::lanes_fold<0, ReduceTuple, Ps...>(acc, rr);
1446 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, rem);
1450 template <FabArrayType MF,
typename D,
typename F>
1451 requires (IsCallable<F, int, int, int, int, int>::value)
1452 void eval (MF
const& mf, IntVect
const& nghost,
int ncomp, D & reduce_data, F
const& f)
1454 using ReduceTuple =
typename D::Type;
1456#pragma omp parallel if (!system::regtest_reduction)
1460 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rem);
1461 Reduce::detail::Lanes<ReduceTuple> acc;
1462 Reduce::detail::lanes_set<0>(acc, rem);
1463 for (MFIter mfi(mf,
true); mfi.isValid(); ++mfi) {
1464 Box const& b = mfi.growntilebox(nghost);
1465 const int li = mfi.LocalIndex();
1468 for (
int n = 0; n < ncomp; ++n) {
1469 for (
int k = lo.z; k <= hi.z; ++k) {
1470 for (
int j = lo.y; j <= hi.y; ++j) {
1471 Reduce::detail::reduce_row<Ps...>(lo.x, hi.x, acc, rem,
1472 [&] (
int i) {
return f(li,i,j,k,n); });
1475 auto& rr = reduce_data.reference(OpenMP::get_thread_num());
1476 Reduce::detail::lanes_fold<0, ReduceTuple, Ps...>(acc, rr);
1477 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, rem);
1481 template <
typename D,
typename F,
int dim>
1482 void eval (BoxND<dim>
const& box, D & reduce_data, F&& f)
1484 using ReduceTuple =
typename D::Type;
1486 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rr);
1487 call_f_box<D>(box, rr, std::forward<F>(f));
1488 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(
1489 reduce_data.reference(OpenMP::get_thread_num()), rr);
1492 template <std::
integral N,
typename D,
typename F,
int dim>
1493 void eval (BoxND<dim>
const& box, N ncomp, D & reduce_data, F
const& f)
1495 using ReduceTuple =
typename D::Type;
1497 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rem);
1498 Reduce::detail::Lanes<ReduceTuple> acc;
1499 Reduce::detail::lanes_set<0>(acc, rem);
1500 int const ilo = box.smallEnd(0);
1501 int const ihi = box.bigEnd(0);
1502 BoxND<dim> rows = box;
1503 rows.setBig(0, ilo);
1504 For(rows, ncomp, [&] (IntVectND<dim> iv,
int n) {
1505 Reduce::detail::reduce_row<Ps...>(ilo, ihi, acc, rem, [&] (
int i) {
1507 return Reduce::detail::call_f_intvect_n(f, iv, n);
1510 auto& rr = reduce_data.reference(OpenMP::get_thread_num());
1511 Reduce::detail::lanes_fold<0, ReduceTuple, Ps...>(acc, rr);
1512 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, rem);
1515 template <std::
integral N,
typename D,
typename F>
1516 void eval (N n, D & reduce_data, F
const& f)
1518 using ReduceTuple =
typename D::Type;
1520 Reduce::detail::for_each_init<0, ReduceTuple, Ps...>(rem);
1521 Reduce::detail::Lanes<ReduceTuple> acc;
1522 Reduce::detail::lanes_set<0>(acc, rem);
1524 Reduce::detail::reduce_row<Ps...>(N(0),
static_cast<N
>(n-1), acc, rem,
1525 [&] (N i) {
return f(i); });
1527 auto& rr = reduce_data.reference(OpenMP::get_thread_num());
1528 Reduce::detail::lanes_fold<0, ReduceTuple, Ps...>(acc, rr);
1529 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rr, rem);
1532 template <
typename D>
1533 typename D::Type value (D & reduce_data)
1535 auto& rrv = reduce_data.reference();
1536 if (! m_result_is_ready) {
1537 using ReduceTuple =
typename D::Type;
1538 if (rrv.size() > 1) {
1539 for (
int i = 1, N = rrv.size(); i < N; ++i) {
1540 Reduce::detail::for_each_local<0, ReduceTuple, Ps...>(rrv[0], rrv[i]);
1543 m_result_is_ready =
true;
1549 template <
typename... T>
friend class ReduceData;
1550 bool m_result_is_ready =
false;
1551 void resetResultReadiness () { m_result_is_ready =
false; }
1556template <
typename T, std::
integral N,
typename F>
1557requires (!std::same_as<T*,std::decay_t<F>>)
1558T Sum (N n, F
const& f, T init_val)
1560 auto const cn = Reduce::detail::chunks_1d(n);
1561 N
const chunk = cn.first;
1562 N
const nchunks = cn.second;
1565#pragma omp parallel for reduction(+:r)
1567 for (N ic = 0; ic < nchunks; ++ic) {
1568 N
const ib = ic*chunk;
1569 N
const ie = (n - ib < chunk) ? n : ib + chunk;
1570 using Tup = GpuTuple<T>;
1572 Reduce::detail::Lanes<Tup> acc;
1573 Reduce::detail::lanes_set<0>(acc, rem);
1574 Reduce::detail::reduce_row<ReduceOpSum>(ib,
static_cast<N
>(ie-1), acc, rem,
1575 [&] (N i) {
return Tup{f(i)}; });
1576 Reduce::detail::lanes_fold<0,Tup,ReduceOpSum>(acc, rem);
1582template <
typename T, std::
integral N>
1583T
Sum (N n, T
const* v, T init_val)
1585 return Sum(n, [=] (N i) -> T {
return v[i]; }, init_val);
1588template <
typename T, std::
integral N,
typename F>
1589requires (!std::same_as<T*,std::decay_t<F>>)
1590T Min (N n, F
const& f, T init_val)
1592 auto const cn = Reduce::detail::chunks_1d(n);
1593 N
const chunk = cn.first;
1594 N
const nchunks = cn.second;
1597#pragma omp parallel for reduction(min:r)
1599 for (N ic = 0; ic < nchunks; ++ic) {
1600 N
const ib = ic*chunk;
1601 N
const ie = (n - ib < chunk) ? n : ib + chunk;
1602 using Tup = GpuTuple<T>;
1604 Reduce::detail::Lanes<Tup> acc;
1605 Reduce::detail::lanes_set<0>(acc, rem);
1606 Reduce::detail::reduce_row<ReduceOpMin>(ib,
static_cast<N
>(ie-1), acc, rem,
1607 [&] (N i) {
return Tup{f(i)}; });
1608 Reduce::detail::lanes_fold<0,Tup,ReduceOpMin>(acc, rem);
1614template <
typename T, std::
integral N>
1615T
Min (N n, T
const* v, T init_val)
1617 return Reduce::Min(n, [=] (N i) -> T {
return v[i]; }, init_val);
1620template <
typename T, std::
integral N,
typename F>
1621requires (!std::same_as<T*,std::decay_t<F>>)
1622T Max (N n, F
const& f, T init_val)
1624 auto const cn = Reduce::detail::chunks_1d(n);
1625 N
const chunk = cn.first;
1626 N
const nchunks = cn.second;
1629#pragma omp parallel for reduction(max:r)
1631 for (N ic = 0; ic < nchunks; ++ic) {
1632 N
const ib = ic*chunk;
1633 N
const ie = (n - ib < chunk) ? n : ib + chunk;
1634 using Tup = GpuTuple<T>;
1636 Reduce::detail::Lanes<Tup> acc;
1637 Reduce::detail::lanes_set<0>(acc, rem);
1638 Reduce::detail::reduce_row<ReduceOpMax>(ib,
static_cast<N
>(ie-1), acc, rem,
1639 [&] (N i) {
return Tup{f(i)}; });
1640 Reduce::detail::lanes_fold<0,Tup,ReduceOpMax>(acc, rem);
1646template <
typename T, std::
integral N>
1647T
Max (N n, T
const* v, T init_val)
1649 return Reduce::Max(n, [=] (N i) -> T {
return v[i]; }, init_val);
1652template <
typename T, std::
integral N,
typename F>
1653requires (!std::same_as<T*,std::decay_t<F>>)
1654std::pair<T,T> MinMax (N n, F
const& f)
1656 auto const cn = Reduce::detail::chunks_1d(n);
1657 N
const chunk = cn.first;
1658 N
const nchunks = cn.second;
1659 T r_min = std::numeric_limits<T>::max();
1660 T r_max = std::numeric_limits<T>::lowest();
1662#pragma omp parallel for reduction(min:r_min) reduction(max:r_max)
1664 for (N ic = 0; ic < nchunks; ++ic) {
1665 N
const ib = ic*chunk;
1666 N
const ie = (n - ib < chunk) ? n : ib + chunk;
1667 using Tup = GpuTuple<T,T>;
1668 Tup rem{std::numeric_limits<T>::max(), std::numeric_limits<T>::lowest()};
1669 Reduce::detail::Lanes<Tup> acc;
1670 Reduce::detail::lanes_set<0>(acc, rem);
1671 Reduce::detail::reduce_row<ReduceOpMin,ReduceOpMax>(ib,
static_cast<N
>(ie-1), acc, rem,
1672 [&] (N i) { T
const tmp = f(i);
return Tup{tmp,tmp}; });
1673 Reduce::detail::lanes_fold<0,Tup,ReduceOpMin,ReduceOpMax>(acc, rem);
1677 return std::make_pair(r_min,r_max);
1680template <
typename T, std::
integral N>
1681std::pair<T,T>
MinMax (N n, T
const* v)
1683 return Reduce::MinMax<T>(n, [=] (N i) -> T {
return v[i]; });
1686template <
typename T, std::
integral N,
typename P>
1687bool AnyOf (N n, T
const* v, P
const& pred)
1689 return std::any_of(v, v+n, pred);
1692template <
typename P,
int dim>
1693bool AnyOf (BoxND<dim>
const& box, P
const& pred)
1695 for (
auto iv : box.iterator()) {
1696 if (Reduce::detail::call_f_intvect(pred, iv)) {
return true; }
1709template <
typename... Ts,
typename... Ps>
1711constexpr GpuTuple<Ts...>
1715 Reduce::detail::for_each_init<0,
decltype(r), Ps...>(r);
1723template <
typename... Ts,
typename... Ps>
1725constexpr GpuTuple<Ts...>
1729 Reduce::detail::for_each_init<0,
decltype(r), Ps...>(r);
1734template <
typename Ops,
typename Ts>
1737template <
typename... Ops,
typename... Ts>
1738class ReducerImpl<TypeList<Ops...>, TypeList<Ts...>>
1741 static_assert(
sizeof...(Ops) > 0);
1742 static_assert(
sizeof...(Ts) > 0);
1743 static_assert(
sizeof...(Ops) ==
sizeof...(Ts));
1746 : m_reduce_data(m_reduce_op)
1750 using Result_t = GpuTuple<Ts...>;
1751 ReduceOps<Ops...> m_reduce_op;
1752 ReduceData<Ts...> m_reduce_data;
1820template <
typename Ops,
typename Ts>
1822 :
public ReducerImpl<ToTypeList_t<Ops>, ToTypeList_t<Ts>>
1836 void operator= (
Reducer const&) =
delete;
1837 void operator= (
Reducer &&) =
delete;
1853 template <
typename F,
int dim>
1858 this->m_reduce_op.eval(box, this->m_reduce_data, std::forward<F>(f));
1876 template <
typename F,
int dim>
1881 this->m_reduce_op.eval(box, ncomp, this->m_reduce_data, std::forward<F>(f));
1903 template <FabArrayType MF,
typename F>
1907 this->m_reduce_op.eval(mf, nghost, this->m_reduce_data, std::forward<F>(f));
1932 template <FabArrayType MF,
typename F>
1936 this->m_reduce_op.eval(mf, nghost, ncomp, this->m_reduce_data, std::forward<F>(f));
1951 template <
typename N,
typename F>
1955 this->m_reduce_op.eval(n, this->m_reduce_data, std::forward<F>(f));
1970 return this->m_reduce_data.value(this->m_reduce_op);
Runtime initialization/finalization helpers and global diagnostics.
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.
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:846
static unsigned int maxBlocksPerLaunch() noexcept
Definition AMReX_GpuDevice.H:242
static constexpr int warp_size
Definition AMReX_GpuDevice.H:239
static bool usingExternalStream() noexcept
Definition AMReX_GpuDevice.cpp:973
Cell-Based or Node-Based Indices.
Definition AMReX_IndexType.H:36
An Integer Vector in dim-Dimensional Space.
Definition AMReX_IntVect.H:149
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
T * data() noexcept
Definition AMReX_PODVector.H:672
Definition AMReX_Reduce.H:556
~ReduceData()
Definition AMReX_Reduce.H:578
int maxStreamIndex() const
Definition AMReX_Reduce.H:618
Type value()
Definition AMReX_Reduce.H:591
void updateMaxStreamIndex(gpuStream_t const &s)
Definition AMReX_Reduce.H:619
int & nBlocks(gpuStream_t const &s)
Definition AMReX_Reduce.H:614
GpuTuple< Ts... > Type
Definition AMReX_Reduce.H:558
ReduceData(ReduceOps< Ps... > &reduce_op)
Definition AMReX_Reduce.H:561
void markValueCalled() noexcept
Definition AMReX_Reduce.H:623
Type * devicePtr(gpuStream_t const &s)
Definition AMReX_Reduce.H:607
Type value(ReduceOps< Ps... > &reduce_op)
Definition AMReX_Reduce.H:599
Type * devicePtr()
Definition AMReX_Reduce.H:606
GpuArray< int, 8 > & nBlocks()
Definition AMReX_Reduce.H:613
ReduceData(ReduceData< Ts... > const &)=delete
Type * hostPtr()
Definition AMReX_Reduce.H:611
int maxBlocks() const
Definition AMReX_Reduce.H:616
ReduceData(ReduceData< Ts... > &&)=delete
Definition AMReX_Reduce.H:715
void eval(BoxND< dim > const &box, N ncomp, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:916
D::Type value(D &reduce_data)
Definition AMReX_Reduce.H:983
void eval(BoxND< dim > const &box, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:910
void eval(MF const &mf, IntVect const &nghost, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:852
friend class ReduceData
Definition AMReX_Reduce.H:1071
void eval(MF const &mf, IntVect const &nghost, int ncomp, D &reduce_data, F &&f)
Definition AMReX_Reduce.H:878
void eval(N n, D &reduce_data, F const &f)
Definition AMReX_Reduce.H:931
static constexpr int size
Number of reduction operators.
Definition AMReX_Reduce.H:1828
Result_t getResult()
Get the final reduction result.
Definition AMReX_Reduce.H:1968
typename Base::Result_t Result_t
Reduction result type, GpuTuple<U...>, where U... are the types in Ts.
Definition AMReX_Reduce.H:1827
void eval(BoxND< dim > const &box, F &&f)
Reduction over a Box.
Definition AMReX_Reduce.H:1856
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:1102
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:1176
std::pair< T, T > MinMax(N n, T const *v)
Compute the minimum and maximum of an array of values.
Definition AMReX_Reduce.H:1148
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:1125
T Sum(N n, T const *v, T init_val=0)
Compute the sum of an array of values.
Definition AMReX_Reduce.H:1079
__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:1328
PODVector< T, PinnedArenaAllocator< T > > PinnedVector
A PODVector that uses the pinned memory arena.
Definition AMReX_GpuContainers.H:48
PODVector< T, ArenaAllocator< T > > DeviceVector
A PODVector that uses the standard memory Arena. Note that the memory might or might not be managed d...
Definition AMReX_GpuContainers.H:24
Arena * The_Pinned_Arena()
Definition AMReX_Arena.cpp:879
Arena * The_Arena()
Definition AMReX_Arena.cpp:839
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:54
__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
Definition AMReX_BaseFwd.H:60
__device__ T blockReduce(T x, WARPREDUCE &&warp_reduce, T x0)
Definition AMReX_GpuReduce.H:317
__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
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:329
void dtoh_memcpy_async(void *p_h, const void *p_d, const std::size_t sz) noexcept
Definition AMReX_GpuDevice.H:454
gpuStream_t gpuStream() noexcept
Definition AMReX_GpuDevice.H:310
__device__ T blockReduceSum(T source) noexcept
Definition AMReX_GpuReduce.H:353
constexpr int get_max_threads()
Definition AMReX_OpenMP.H:36
Definition AMReX_Reduce.H:22
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:273
@ F
Definition AMReX_Order.H:7
void For(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:400
@ Device
Definition AMReX_GpuControl.H:65
__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:1712
void launch(T const &n, L const &f) noexcept
Definition AMReX_GpuLaunchFunctsC.H:122
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
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
cudaStream_t gpuStream_t
Definition AMReX_GpuControl.H:79
BoxIndexerND< 3 > BoxIndexer
Definition AMReX_Box.H:2610
const int[]
Definition AMReX_BLProfiler.cpp:1665
__global__ void launch_global(L f0, Lambdas... fs)
Definition AMReX_GpuLaunch.H:68
__host__ __device__ constexpr int get(IntVectND< dim > const &iv) noexcept
Get the Idx-th element of IntVectND<dim>.
Definition AMReX_IntVect.H:1360
Utility that maps flattened point indices back to IntVectND coordinates.
Definition AMReX_Box.H:2496
__host__ __device__ IntVectND< dim > intVect(std::uint64_t icell) const
Convert flattened point index icell to its IntVectND coordinate.
Definition AMReX_Box.H:2519
__host__ __device__ std::uint64_t numPts() const
Return the number of points covered by the indexed box.
Definition AMReX_Box.H:2554
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:86
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:409
__host__ __device__ void local_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:430
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:433
__device__ void parallel_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:421
Definition AMReX_Reduce.H:438
__device__ void parallel_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:450
__host__ __device__ void local_update(T &d, T s) const noexcept
Definition AMReX_Reduce.H:459
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:462
Definition AMReX_Reduce.H:375
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:400
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:396
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:387
Definition AMReX_Reduce.H:341
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:366
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:353
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:362
Definition AMReX_Reduce.H:311
__device__ void parallel_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:324
__host__ __device__ void local_update(T &d, T const &s) const noexcept
Definition AMReX_Reduce.H:333
constexpr void init(T &t) const noexcept
Definition AMReX_Reduce.H:336
Struct for holding types.
Definition AMReX_TypeList.H:13