1#ifndef AMREX_DENSEBINS_H_
2#define AMREX_DENSEBINS_H_
3#include <AMReX_Config.H>
16#if defined(AMREX_USE_CUDA) || defined(AMREX_USE_HIP)
31 T warpRunAggregatedIncrement (T* counts, T bin,
bool active)
noexcept
34#if defined(AMREX_USE_HIP)
35 using mask_t =
unsigned long long;
36 const int lane =
static_cast<int>(__lane_id());
37 const mask_t active_mask = __ballot(active);
38 const T prev_bin = __shfl_up(bin, 1);
40 using mask_t =
unsigned int;
41 constexpr mask_t full_mask = 0xffffffffu;
42 const int lane =
static_cast<int>(threadIdx.x) % warp_size;
43 const mask_t active_mask = __ballot_sync(full_mask, active);
44 const T prev_bin = __shfl_up_sync(full_mask, bin, 1);
46 const bool prev_active = (lane > 0) && ((active_mask >> (lane-1)) & 1);
47 const bool head = active && (!prev_active || bin != prev_bin);
48#if defined(AMREX_USE_HIP)
49 const mask_t heads = __ballot(head);
51 const mask_t heads = __ballot_sync(full_mask, head);
54 const mask_t lanes_le = (lane == warp_size-1) ? ~mask_t(0)
55 : (mask_t(1) << (lane+1)) - 1;
62 const mask_t heads_le = heads & lanes_le;
63#if defined(AMREX_USE_HIP)
64 run_start = 63 - __clzll(
static_cast<long long>(heads_le));
66 run_start = 31 - __clz(
static_cast<int>(heads_le));
70 const mask_t ends = (heads | ~active_mask) & ~lanes_le;
71#if defined(AMREX_USE_HIP)
72 const int run_end = (ends != 0) ? __ffsll(
static_cast<long long>(ends)) - 1
75 const int run_end = (ends != 0) ? __ffs(
static_cast<int>(ends)) - 1
80#if defined(AMREX_USE_HIP)
81 base = __shfl(base, run_start);
83 base = __shfl_sync(full_mask, base, run_start);
85 return base +
static_cast<T
>(lane - run_start);
104 static constexpr OpenMPBinPolicy
Default{};
173 template <
typename F,
typename I>
176 if constexpr (
IsCallable<
F,
decltype(v), I>::value) {
207 template <
typename N,
typename F>
234 template <
typename N,
typename F>
262 template <
typename N,
typename F>
265 const auto lo =
lbound(bx);
266 const auto hi =
ubound(bx);
270 auto iv = call_f(f,t,i);
271 auto iv3 = iv.dim3();
272 int nx = hi.x-lo.x+1;
273 int ny = hi.y-lo.y+1;
274 int nz = hi.z-lo.z+1;
278 return (uiz * ny + uiy) * nx + uix;
303 template <
typename N,
typename F>
310 m_bins.resize(nitems);
311 m_perm.resize(nitems);
312 m_local_offsets.resize(nitems);
315 m_counts.resize(nbins+1, 0);
318 m_offsets.resize(nbins+1);
322 index_type* plocal_offsets = m_local_offsets.dataPtr();
323#if defined(AMREX_USE_CUDA) || defined(AMREX_USE_HIP)
326 constexpr int block_size = AMREX_GPU_MAX_THREADS;
327 const auto nblocks =
static_cast<int>((
Long(nitems) + block_size - 1) / block_size);
332 const Long li =
Long(blockIdx.x) * block_size + threadIdx.x;
333 const bool active = li <
Long(nitems);
340 index_type off = detail::warpRunAggregatedIncrement(pcount, bin, active);
342 plocal_offsets[i] = off;
349 pbins[i] = call_f(f,v,i);
351 plocal_offsets[i] = off;
361 index_type index = poffsets[pbins[i]] + plocal_offsets[i];
391 template <
typename N,
typename F>
394 const auto lo =
lbound(bx);
395 const auto hi =
ubound(bx);
399 auto iv = call_f(f,t,i);
400 auto iv3 = iv.dim3();
401 int nx = hi.x-lo.x+1;
402 int ny = hi.y-lo.y+1;
403 int nz = hi.z-lo.z+1;
404 index_type uix = amrex::min(nx-1,amrex::max(0,iv3.x));
405 index_type uiy = amrex::min(ny-1,amrex::max(0,iv3.y));
406 index_type uiz = amrex::min(nz-1,amrex::max(0,iv3.z));
407 return (uiz * ny + uiy) * nx + uix;
433 template <
typename N,
typename F>
438 if (nbins <= 0) {
return; }
442 m_bins.resize(nitems);
443 m_perm.resize(nitems);
446 int chunksize = nitems / nchunks;
448 for (
int i = 0; i < nbins*nchunks; ++i) { counts[i] = 0;}
451 m_counts.resize(nbins+1, 0);
454 m_offsets.resize(nbins+1);
457#pragma omp parallel for
459 for (
int j = 0; j < nchunks; ++j) {
460 int istart = j*chunksize;
461 int istop = (j == nchunks-1) ? nitems : (j+1)*chunksize;
462 for (
int i = istart; i < istop; ++i) {
463 m_bins[i] = call_f(f,v,i);
464 ++counts[nbins*j+m_bins[i]];
469#pragma omp parallel for
471 for (
int i = 0; i < nbins; ++i) {
473 for (
int j = 0; j < nchunks; ++j) {
474 auto tmp = counts[nbins*j+i];
475 counts[nbins*j+i] = total;
483 for (
int i = 0; i < nbins; ++i) {m_offsets[i+1] = m_offsets[i] + m_counts[i];}
486#pragma omp parallel for
488 for (
int i = 0; i < nbins; ++i) {
489 for (
int j = 0; j < nchunks; ++j) {
490 counts[nbins*j+i] += m_offsets[i];
495#pragma omp parallel for
497 for (
int j = 0; j < nchunks; ++j) {
498 int istart = j*chunksize;
499 int istop = (j == nchunks-1) ? nitems : (j+1)*chunksize;
500 for (
int i = istart; i < istop; ++i) {
501 auto bid = m_bins[i];
502 m_perm[counts[nbins*j+bid]++] = i;
532 template <
typename N,
typename F>
535 const auto lo =
lbound(bx);
536 const auto hi =
ubound(bx);
540 auto iv = call_f(f,t,i);
541 auto iv3 = iv.dim3();
542 int nx = hi.x-lo.x+1;
543 int ny = hi.y-lo.y+1;
544 int nz = hi.z-lo.z+1;
545 index_type uix = amrex::min(nx-1,amrex::max(0,iv3.x));
546 index_type uiy = amrex::min(ny-1,amrex::max(0,iv3.y));
547 index_type uiz = amrex::min(nz-1,amrex::max(0,iv3.z));
548 return (uiz * ny + uiy) * nx + uix;
574 template <
typename N,
typename F>
581 m_bins.resize(nitems);
582 m_perm.resize(nitems);
585 m_counts.resize(nbins+1, 0);
588 m_offsets.resize(nbins+1);
590 for (N i = 0; i < nitems; ++i) {
591 m_bins[i] = call_f(f,v,i);
592 ++m_counts[m_bins[i]];
599 for (N i = 0; i < nitems; ++i) {
606 [[nodiscard]]
Long numItems () const noexcept {
return m_perm.size(); }
609 [[nodiscard]]
Long numBins () const noexcept {
return m_offsets.size()-1; }
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#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.
virtual void * alloc(std::size_t sz)=0
Allocate sz bytes from this arena.
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:385
A container for storing items in a set of bins.
Definition AMReX_DenseBins.H:155
std::conditional_t< IsParticleTileData< T >(), T, const T * > const_pointer_type
Definition AMReX_DenseBins.H:164
const index_type * permutationPtr() const noexcept
returns const pointer to the permutation array
Definition AMReX_DenseBins.H:621
std::conditional_t< IsParticleTileData< T >(), const T &, const T * > const_pointer_input_type
Definition AMReX_DenseBins.H:169
DenseBinIteratorFactory< T > getBinIteratorFactory() const noexcept
returns a GPU-capable object that can create iterators over the items in a bin.
Definition AMReX_DenseBins.H:630
const index_type * binsPtr() const noexcept
returns the const pointer to the bins array
Definition AMReX_DenseBins.H:627
index_type * offsetsPtr() noexcept
returns the pointer to the offsets array
Definition AMReX_DenseBins.H:615
index_type * permutationPtr() noexcept
returns the pointer to the permutation array
Definition AMReX_DenseBins.H:612
void build(BinPolicy::OpenMPBinPolicy, N nitems, const_pointer_input_type v, const Box &bx, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:392
void build(BinPolicy::GPUBinPolicy, N nitems, const_pointer_input_type v, const Box &bx, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:263
void build(N nitems, const_pointer_input_type v, const Box &bx, F &&f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:208
int index_type
Definition AMReX_DenseBins.H:159
void build(BinPolicy::SerialBinPolicy, N nitems, const_pointer_input_type v, const Box &bx, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:533
void build(BinPolicy::GPUBinPolicy, N nitems, const_pointer_input_type v, int nbins, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:304
const index_type * offsetsPtr() const noexcept
returns const pointer to the offsets array
Definition AMReX_DenseBins.H:624
void build(BinPolicy::OpenMPBinPolicy, N nitems, const_pointer_input_type v, int nbins, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:434
void build(N nitems, const_pointer_input_type v, int nbins, F &&f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:235
Long numItems() const noexcept
the number of items in the container
Definition AMReX_DenseBins.H:606
void build(BinPolicy::SerialBinPolicy, N nitems, const_pointer_input_type v, int nbins, F const &f)
Populate the bins with a set of items.
Definition AMReX_DenseBins.H:575
Long numBins() const noexcept
the number of bins in the container
Definition AMReX_DenseBins.H:609
index_type * binsPtr() noexcept
returns the pointer to the bins array
Definition AMReX_DenseBins.H:618
static void streamSynchronize() noexcept
Definition AMReX_GpuDevice.cpp:861
static constexpr int warp_size
Definition AMReX_GpuDevice.H:236
Dynamically allocated vector for trivially copyable data.
Definition AMReX_PODVector.H:308
amrex_long Long
Definition AMReX_INT.H:30
OutIter exclusive_scan(InIter begin, InIter end, OutIter result)
Definition AMReX_Scan.H:1181
__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
Arena * The_Arena()
Definition AMReX_Arena.cpp:829
__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
static constexpr OpenMPBinPolicy OpenMP
Definition AMReX_DenseBins.H:98
static constexpr GPUBinPolicy Default
Definition AMReX_DenseBins.H:102
static constexpr SerialBinPolicy Serial
Definition AMReX_DenseBins.H:99
static constexpr GPUBinPolicy GPU
Definition AMReX_DenseBins.H:97
__host__ __device__ AMREX_FORCE_INLINE T Add(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:200
void copy(HostToDevice, InIter begin, InIter end, OutIter result) noexcept
A host-to-device copy routine. Note this is just a wrapper around memcpy, so it assumes contiguous st...
Definition AMReX_GpuContainers.H:128
static constexpr DeviceToDevice deviceToDevice
Definition AMReX_GpuContainers.H:107
gpuStream_t gpuStream() noexcept
Definition AMReX_GpuDevice.H:291
constexpr int get_max_threads()
Definition AMReX_OpenMP.H:36
Definition AMReX_Amr.cpp:50
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
const int[]
Definition AMReX_BLProfiler.cpp:1665
Definition AMReX_BinIterator.H:24
Definition AMReX_DenseBins.H:93
Definition AMReX_DenseBins.H:94
Definition AMReX_DenseBins.H:95
Definition AMReX_DenseBins.H:110
DenseBinIteratorFactory(const Gpu::DeviceVector< index_type > &offsets, const Gpu::DeviceVector< index_type > &permutation, const T *items)
Definition AMReX_DenseBins.H:118
const index_type * m_permutation_ptr
Definition AMReX_DenseBins.H:133
int index_type
Definition AMReX_DenseBins.H:111
__host__ __device__ BinIterator< T > getBinIterator(const int bin_number) const noexcept
Definition AMReX_DenseBins.H:127
const_pointer_type m_items
Definition AMReX_DenseBins.H:134
const index_type * m_offsets_ptr
Definition AMReX_DenseBins.H:132
std::conditional_t< IsParticleTileData< T >(), T, const T * > const_pointer_type
Definition AMReX_DenseBins.H:116
Test if a given type T is callable with arguments of type Args...
Definition AMReX_TypeTraits.H:208