1#ifndef AMREX_BASEFAB_UTILITY_H_
2#define AMREX_BASEFAB_UTILITY_H_
3#include <AMReX_Config.H>
27template <
class Tto,
class Tfrom>
33 auto const& tdata = tofab.array();
34 auto const& fdata = fromfab.const_array();
37 tdata(i,j,k,n+dcomp.i) = static_cast<Tto>(fdata(i,j,k,n+scomp.i));
54template <
typename STRUCT,
typename F>
55requires ((
sizeof(STRUCT)<=36*8) &&
57 std::is_trivially_destructible_v<STRUCT>)
60 Box const& box = aos_fab.
box();
61 auto const& aos = aos_fab.
array();
62 using T =
typename STRUCT::value_type;
63 constexpr int STRUCTSIZE =
sizeof(STRUCT)/
sizeof(T);
64 static_assert(
sizeof(STRUCT) ==
sizeof(T)*STRUCTSIZE,
65 "amrex::fill: sizeof(STRUCT) != sizeof(T)*STRUCTSIZE");
69 const auto ntotcells = std::uint64_t(box.
numPts());
70 constexpr int nthreads_per_block = (STRUCTSIZE <= 8) ? 256 : 128;
71 std::uint64_t nblocks_long = (ntotcells+nthreads_per_block-1)/nthreads_per_block;
72 AMREX_ASSERT(nblocks_long <= std::uint64_t(std::numeric_limits<int>::max()));
73 auto nblocks =
int(nblocks_long);
74 std::size_t shared_mem_bytes = nthreads_per_block *
sizeof(STRUCT);
77 amrex::launch<nthreads_per_block>(nblocks, shared_mem_bytes,
Gpu::gpuStream(),
80 auto const icell = std::uint64_t(handler.globalIdx());
81 std::uint64_t
const blockDimx = handler.blockDim();
82 std::uint64_t
const threadIdxx = handler.threadIdx();
83 std::uint64_t
const blockIdxx = handler.blockIdx();
84 auto const shared = (T*)handler.sharedMemory();
85 if (icell < indexer.
numPts()) {
86 auto ga =
new(shared+threadIdxx*STRUCTSIZE) STRUCT;
87 auto [i, j, k] = indexer(icell);
90 handler.sharedBarrier();
91 for (std::uint64_t m = threadIdxx,
92 mend = amrex::min<std::uint64_t>(blockDimx, indexer.
numPts()-blockDimx*blockIdxx) * STRUCTSIZE;
93 m < mend; m += blockDimx) {
94 p[blockDimx*blockIdxx*STRUCTSIZE+m] = shared[m];
98 amrex::launch<nthreads_per_block>(nblocks, shared_mem_bytes,
Gpu::gpuStream(),
101 std::uint64_t
const icell = std::uint64_t(blockDim.x)*blockIdx.x+threadIdx.x;
103 T*
const shared = gsm.
dataPtr();
104 if (icell < indexer.
numPts()) {
105 auto ga =
new(shared+std::uint64_t(threadIdx.x)*STRUCTSIZE) STRUCT;
106 auto [i, j, k] = indexer(icell);
110 for (std::uint64_t m = threadIdx.x,
111 mend = amrex::min<std::uint64_t>(blockDim.x, indexer.
numPts()-std::uint64_t(blockDim.x)*blockIdx.x) * STRUCTSIZE;
112 m < mend; m += blockDim.x) {
113 p[std::uint64_t(blockDim.x)*blockIdx.x*STRUCTSIZE+m] = shared[m];
122 f(aos(i,j,k), i, j, k);
146#if defined(AMREX_USE_CUDA) || defined(AMREX_USE_HIP)
148 constexpr int tile_dim = 32;
149 constexpr int block_rows = 16;
150 constexpr int nthreads = tile_dim*block_rows;
156 dim3 block{unsigned(tile_dim), unsigned(block_rows), 1};
157 dim3 grid{unsigned((nx+tile_dim-1)/tile_dim),
158 unsigned((nz+tile_dim-1)/tile_dim),
159 unsigned(std::min(ny, 65535))};
164 __shared__ T tile[tile_dim][tile_dim+1];
166 for (
unsigned int j = blockIdx.z; j < unsigned(ny); j += gridDim.z) {
168 int k = blockIdx.y * tile_dim + threadIdx.x;
169 int i = blockIdx.x * tile_dim + threadIdx.y;
172 for (
int it = 0; it < tile_dim; it += block_rows, i += block_rows) {
175 tile[threadIdx.y+it][threadIdx.x] = pi[k + (j+i*std::size_t(ny))*nz];
182 i = blockIdx.x * tile_dim + threadIdx.x;
183 k = blockIdx.y * tile_dim + threadIdx.y;
186 for (
int it = 0; it < tile_dim; it += block_rows, k += block_rows) {
188 po[i + (j+k*std::size_t(ny))*nx] = tile[threadIdx.x][threadIdx.y+it];
198#elif defined(AMREX_USE_SYCL)
200 constexpr int tile_dim = 32;
201 constexpr int block_rows = 8;
206 sycl::range<3> block{std::size_t(1), std::size_t(block_rows), std::size_t(tile_dim)};
207 sycl::range<3> grid{std::size_t(ny), std::size_t((nz+tile_dim-1)/tile_dim),
208 std::size_t((nx+tile_dim-1)/tile_dim)};
209 sycl::range<3> global_size{grid[0]*block[0],
215 q.submit([&] (sycl::handler& h)
217 auto tile = sycl::local_accessor<T,2>(sycl::range<2>(tile_dim,tile_dim+1),h);
219 h.parallel_for(sycl::nd_range<3>(global_size, block),
220 [=] (sycl::nd_item<3> item)
222 auto group = item.get_group();
223 dim3 blockIdx{unsigned(group.get_group_id(2)),
224 unsigned(group.get_group_id(1)),
225 unsigned(group.get_group_id(0))};
226 dim3 threadIdx{unsigned(item.get_local_id(2)),
227 unsigned(item.get_local_id(1)),
228 unsigned(item.get_local_id(0))};
230 int k = blockIdx.y * tile_dim + threadIdx.x;
231 int i = blockIdx.x * tile_dim + threadIdx.y;
236 for (
int it = 0; it < tile_dim; it += block_rows, i += block_rows) {
239 tile[threadIdx.y+it][threadIdx.x] = pi[k + (j+i*std::size_t(ny))*nz];
244 item.barrier(sycl::access::fence_space::local_space);
246 i = blockIdx.x * tile_dim + threadIdx.x;
247 k = blockIdx.y * tile_dim + threadIdx.y;
250 for (
int it = 0; it < tile_dim; it += block_rows, k += block_rows) {
252 po[i + (j+k*std::size_t(ny))*nx] = tile[threadIdx.x][threadIdx.y+it];
258 }
catch (sycl::exception
const& ex) {
259 amrex::Abort(std::string(
"transposeCtoF: ")+ex.what()+
"!!!!!");
264 constexpr int bx = 32;
265 constexpr int bz = 32;
267 std::size_t nxy = std::size_t(nx) * ny;
268 std::size_t nyz = std::size_t(ny) * nz;
271#pragma omp parallel for collapse(3)
273 for (
int j = 0; j < ny; ++j) {
274 for (
int k0 = 0; k0 < nz; k0 += bz) {
275 for (
int i0 = 0; i0 < nx; i0 += bx) {
276 int imax = std::min(i0+bx, nx);
277 int kmax = std::min(k0+bz, nz);
280 for (
int i = i0; i < imax; ++i) {
282 for (
int k = k0; k < kmax; ++k) {
283 pdst[i + k*nxy] = psrc[k + i*nyz];
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
BaseFab container template providing box-based field storage.
#define AMREX_PRAGMA_SIMD
Definition AMReX_Extension.H:85
#define AMREX_RESTRICT
Definition AMReX_Extension.H:37
#define AMREX_GPU_ERROR_CHECK()
Definition AMReX_GpuError.H:151
#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
Real * pdst
Definition AMReX_HypreMLABecLap.cpp:1132
#define AMREX_IS_TRIVIALLY_COPYABLE(T)
Definition AMReX_TypeTraits.H:10
A FortranArrayBox(FAB)-like object.
Definition AMReX_BaseFab.H:222
const Box & box() const noexcept
Returns the domain (box) where the array is defined.
Definition AMReX_BaseFab.H:357
Array4< T const > array() const noexcept
Create an Array4 view over all components.
Definition AMReX_BaseFab.H:475
T * dataPtr(int n=0) noexcept
Returns a pointer to an object of type T that is the value of the Nth component associated with the c...
Definition AMReX_BaseFab.H:418
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:385
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:88
gpuStream_t gpuStream() noexcept
Definition AMReX_GpuDevice.H:291
Definition AMReX_Amr.cpp:50
void fill(BaseFab< STRUCT > &aos_fab, F const &f)
Fill an array-of-structs BaseFab by invoking a functor per cell.
Definition AMReX_BaseFabUtility.H:58
void transposeCtoF(T const *pi, T *po, int nx, int ny, int nz)
Transpose a 3D array of shape (nx, ny, nz) from C-order to Fortran-order storage.
Definition AMReX_BaseFabUtility.H:142
__host__ __device__ void cast(BaseFab< Tto > &tofab, BaseFab< Tfrom > const &fromfab, Box const &bx, SrcComp scomp, DestComp dcomp, NumComps ncomp) noexcept
Cast components from one BaseFab to another over a region.
Definition AMReX_BaseFabUtility.H:30
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:242
const int[]
Definition AMReX_BLProfiler.cpp:1665
void LoopOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:365
__host__ __device__ void LoopConcurrent(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:152
Utility that maps flattened point indices back to IntVectND coordinates.
Definition AMReX_Box.H:2494
__host__ __device__ std::uint64_t numPts() const
Return the number of points covered by the indexed box.
Definition AMReX_Box.H:2552
Destination-component descriptor.
Definition AMReX_BaseFab.H:107
Definition AMReX_GpuTypes.H:88
Definition AMReX_GpuMemory.H:126
__device__ T * dataPtr() noexcept
Definition AMReX_GpuMemory.H:127
Number-of-components descriptor.
Definition AMReX_BaseFab.H:114
Source-component descriptor.
Definition AMReX_BaseFab.H:100