35template <
class T0,
class T1>
39 operator() (T0* d, T1 s)
const noexcept
41 *d =
static_cast<T0
>(s);
45template <
class T0,
class T1>
49 operator() (T0* d, T1 s)
const noexcept
51 *d +=
static_cast<T0
>(s);
55template <
class T0,
class T1>
59 requires (amrex::HasAtomicAdd<U0>::value)
61 operator() (U0* d, T1 s)
const noexcept
63 Gpu::Atomic::AddNoRet(d,
static_cast<U0
>(s));
67template <
class T0,
class T1,
class F>
69fab_to_fab (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
int dcomp,
int ncomp,
72 TagVector<Array4CopyTag<T0, T1>> tv{copy_tags};
74 detail::ParallelFor_doit(tv,
76 int icell,
int ncells,
int i,
int j,
int k, Array4CopyTag<T0, T1>
const& tag)
noexcept
79 for (
int n = 0; n < ncomp; ++n) {
80 f(&(tag.dfab(i,j,k,n+dcomp)),
81 tag.sfab(i+tag.offset.x,j+tag.offset.y,k+tag.offset.z,n+scomp));
87template <
class TagType,
class F>
89fab_to_fab_store (Vector<TagType>
const& tags,
int scomp,
int dcomp,
int ncomp,
F&&f)
96 for (
int n = 0; n < ncomp; ++n) {
97 f(&(tag.dfab(i,j,k,n+dcomp)),
98 tag.sfab(i+tag.offset.x,j+tag.offset.y,k+tag.offset.z,n+scomp));
104template <
class TagType,
class F>
106fab_to_fab_other (Vector<TagType>
const& tags,
int scomp,
int dcomp,
int ncomp,
F&&f)
111 int* m = &(tag.mask(i,j,k));
112 bool my_turn =
false;
114#if defined(AMREX_USE_SYCL)
120#if defined(AMREX_USE_SYCL)
121 sycl::atomic_fence(sycl::memory_order::acq_rel, sycl::memory_scope::device);
125 for (
int n = 0; n < ncomp; ++n) {
126 f(&(tag.dfab(i,j,k,n+dcomp)),
127 tag.sfab(i+tag.offset.x,j+tag.offset.y,k+tag.offset.z,n+scomp));
129#if defined(AMREX_USE_SYCL)
130 sycl::atomic_fence(sycl::memory_order::acq_rel, sycl::memory_scope::device);
137#if defined(AMREX_USE_CUDA)
139#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ < 700)
142 for (
int c = 0; c < 2; ++c) {
146 for (
int c = 0; c < 2; ++c) {
147 __asm__
volatile(
"");
154#elif defined(AMREX_USE_HIP)
156 __builtin_amdgcn_s_sleep(1);
158#elif defined(AMREX_USE_SYCL)
160 for (
int c = 0; c < 2; ++c) {
161 __asm__
volatile(
"");
170template <
class T0,
class T1,
class F>
172fab_to_fab (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
int dcomp,
173 int ncomp,
F && f, Vector<Array4Tag<int> >
const& masks)
175 using TagType = Array4MaskCopyTag<T0, T1>;
176 Vector<TagType> tags;
177 const int N = copy_tags.size();
179 for (
int i = 0; i < N; ++i) {
180 tags.push_back(TagType{.dfab = copy_tags[i].dfab, .sfab = copy_tags[i].sfab,
181 .mask = masks[i].dfab, .dbox = copy_tags[i].dbox,
182 .offset = copy_tags[i].offset});
185 if constexpr (std::is_same_v<F, CellStore<T0,T1>>)
187 fab_to_fab_store(tags, scomp, dcomp, ncomp, std::forward<F>(f));
191 fab_to_fab_other(tags, scomp, dcomp, ncomp, std::forward<F>(f));
196template <
typename T0,
typename T1>
197requires (amrex::IsStoreAtomic<T0>::value)
199fab_to_fab_atomic_cpy (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
200 int dcomp,
int ncomp, Vector<Array4Tag<int> >
const&)
202 fab_to_fab<T0, T1>(copy_tags, scomp, dcomp, ncomp, CellStore<T0, T1>());
205template <
typename T0,
typename T1>
206requires (!amrex::IsStoreAtomic<T0>::value)
208fab_to_fab_atomic_cpy (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
209 int dcomp,
int ncomp, Vector<Array4Tag<int> >
const& masks)
211 fab_to_fab(copy_tags, scomp, dcomp, ncomp, CellStore<T0, T1>(), masks);
214template <
typename T0,
typename T1>
215requires (amrex::HasAtomicAdd<T0>::value)
217fab_to_fab_atomic_add (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
218 int dcomp,
int ncomp, Vector<Array4Tag<int> >
const&)
220 fab_to_fab(copy_tags, scomp, dcomp, ncomp, CellAtomicAdd<T0, T1>());
223template <
typename T0,
typename T1>
224requires (!amrex::HasAtomicAdd<T0>::value)
226fab_to_fab_atomic_add (Vector<Array4CopyTag<T0, T1> >
const& copy_tags,
int scomp,
227 int dcomp,
int ncomp, Vector<Array4Tag<int> >
const& masks)
229 fab_to_fab(copy_tags, scomp, dcomp, ncomp, CellAdd<T0, T1>(), masks);
232template <
typename T0,
typename T1,
class F>
233void deterministic_fab_to_fab (Vector<Array4CopyTag<T0,T1>>
const& a_tags,
int scomp,
234 int dcomp,
int ncomp,
F const& f)
236 if (a_tags.empty()) {
return; }
238 using TagType = Array4CopyTag<T0,T1>;
242 std::pair<int,Box> dindex_tilebox;
243 bool operator< (TiledTag
const& rhs)
const noexcept {
244 return this->dindex_tilebox < rhs.dindex_tilebox;
246 bool operator!= (TiledTag
const& rhs)
const noexcept {
247 return this->dindex_tilebox != rhs.dindex_tilebox;
250 Vector<TiledTag> tiled_tags;
252 auto const ixtype = a_tags[0].dbox.ixType();
254 constexpr int tile_size = 64;
255 for (
int itag = 0; itag < a_tags.size(); ++itag) {
256 auto const& tag = a_tags[itag];
257 auto const& dlo = tag.dbox.smallEnd();
258 auto const& dhi = tag.dbox.bigEnd();
265#if (AMREX_SPACEDIM == 3)
266 for (
int kt = tlo[2]; kt <= thi[2]; ++kt)
269#if (AMREX_SPACEDIM >= 2)
270 for (
int jt = tlo[1]; jt <= thi[1]; ++jt)
273 for (
int it = tlo[0]; it <= thi[0]; ++it)
278 tiled_tags.push_back(TiledTag{
280 .dindex_tilebox = std::make_pair(tag.dindex,
Box(lo, lo+(tile_size-1), ixtype))
287 std::sort(tiled_tags.begin(), tiled_tags.end());
291 h_tags.reserve(tiled_tags.size());
293 for (
unsigned int itag = 0; itag < tiled_tags.size(); ++itag) {
295 h_ntags.push_back(0);
296 }
else if (tiled_tags[itag-1] != tiled_tags[itag]) {
297 h_ntags.push_back(itag);
299 auto const& ttag = tiled_tags[itag];
300 auto const& btag = a_tags[ttag.tag_index];
301 h_tags.push_back(TagType{.dfab = btag.dfab, .dindex = btag.dindex, .sfab = btag.sfab,
302 .dbox = btag.dbox & ttag.dindex_tilebox.second,
303 .offset = btag.offset});
305 h_ntags.push_back((
unsigned int)tiled_tags.size());
311 auto const* ptag = d_tags.data();
312 auto const* pntags = d_ntags.data();
313 auto const nblocks =
int(h_ntags.size()-1);
314 constexpr auto nthreads = 256;
318 [[sycl::reqd_work_group_size(nthreads)]]
324 Dim1 blockIdx{item.get_group_linear_id()};
325 Dim1 threadIdx{item.get_local_linear_id()};
328 for (
unsigned int itag = pntags[blockIdx.x]; itag < pntags[blockIdx.x+1]; ++itag) {
329 auto const tag = ptag[itag];
330 auto ncells =
int(tag.dbox.numPts());
333 for (
int icell =
int(threadIdx.x); icell < ncells; icell += nthreads) {
334 int k = icell / (len.x*len.y);
335 int j = (icell - k*(len.x*len.y)) / len.x;
336 int i = (icell - k*(len.x*len.y)) - j*len.x;
340 for (
int n = 0; n < ncomp; ++n) {
341 f(tag.dfab.ptr(i,j,k,n+dcomp),
342 tag.sfab(i + tag.offset.x,
344 k + tag.offset.z, n+scomp));
348 if (itag+1 < pntags[blockIdx.x+1]) {
350 sycl::group_barrier(item.get_group());
360template <
typename B,
typename V,
typename TT>
361requires (amrex::HasAtomicAdd<V>::value)
362void unpack_recv_buffer_gpu_atomic_add (
char* pbuffer, TagVector<TT>
const& tv,
363 int dcomp,
int ncomp)
365 detail::ParallelFor_doit(tv,
367 int icell,
int ncells,
int i,
int j,
int k, TT
const& tag)
noexcept
369 if (icell < ncells) {
372 for (
int n = 0; n < ncomp; ++n) {
380template <
typename B,
typename V,
typename TT>
381requires (!amrex::HasAtomicAdd<V>::value)
382void unpack_recv_buffer_gpu_atomic_add (
char* pbuffer, TagVector<TT>
const& tv,
383 int dcomp,
int ncomp)
386 amrex::Abort(
"unpack_recv_buffer_gpu: should NOT get here");
398 auto const& LocTags = *(TheFB.
m_LocTags);
399 auto N_locs =
static_cast<int>(LocTags.size());
400 if (N_locs == 0) {
return; }
405#pragma omp parallel for
407 for (
int i = 0; i < N_locs; ++i)
430 for (
int i = 0; i < N_locs; ++i)
441 loc_copy_tags[tag.
dstIndex].push_back
447 for (
MFIter mfi(*
this); mfi.isValid(); ++mfi)
449 const auto&
tags = loc_copy_tags[mfi];
450 auto dfab = this->
array(mfi);
451 for (
auto const & tag :
tags)
453 auto const sfab = tag.sfab->array();
454 const auto offset = tag.offset.dim3();
456 [=] (
int i,
int j,
int k,
int n)
noexcept
458 dfab(i,j,k,n+scomp) = sfab(i+offset.x,j+offset.y,k+offset.z,n+scomp);
469 auto const& LocTags = *(TheFB.
m_LocTags);
470 auto N_locs =
static_cast<int>(LocTags.size());
471 if (N_locs == 0) {
return; }
475 std::vector<FAB> src_fabs(N_locs);
476 for (
int itag = 0; itag < N_locs; ++itag) {
478 src_fabs[itag].resize(tag.
sbox,ncomp);
479 loc_copy_tags[tag.
dstIndex].push_back
485#pragma omp parallel for
487 for (
int itag = 0; itag < N_locs; ++itag) {
495 for (
MFIter mfi(*
this); mfi.isValid(); ++mfi)
497 const auto&
tags = loc_copy_tags[mfi];
498 const auto& dfab = this->
array(mfi);
499 for (
auto const & tag :
tags)
501 auto const sfab = tag.sfab->array();
502 const auto offset = tag.offset.dim3();
504 [&] (
int i,
int j,
int k,
int n)
noexcept
506 dfab(i,j,k,n+scomp) += sfab(i+offset.x,j+offset.y,k+offset.z,n);
518 auto const& LocTags = *(TheFB.m_LocTags);
519 int N_locs = LocTags.size();
524 if (
auto it = m_fb_local_copy_handler.find(TheFB.m_id);
525 it != m_fb_local_copy_handler.end())
527 tv = it->second.get();
530 loc_copy_tags.reserve(N_locs);
532 for (
int i = 0; i < N_locs; ++i)
540 loc_copy_tags.push_back
541 (TagType{.dfab = this->
atLocalIdx(li).array(),
548 auto utv = std::make_unique<TagVector<TagType>>(loc_copy_tags);
550 m_fb_local_copy_handler[TheFB.m_id] = std::move(utv);
560 auto const& LocTags = *(TheFB.
m_LocTags);
561 int N_locs = LocTags.size();
562 if (N_locs == 0) {
return; }
571 detail::ParallelFor_doit(*tv,
573 int icell,
int ncells,
int i,
int j,
int k, TagType
const& tag)
noexcept
575 if (icell < ncells) {
576 for (
int n = 0; n < ncomp; ++n) {
577 tag.dfab(i,j,k,n+scomp) = tag.sfab(i+tag.offset.x,
579 k+tag.offset.z,n+scomp);
587 loc_copy_tags.reserve(N_locs);
593 masks.reserve(N_locs);
595 for (
int i = 0; i < N_locs; ++i)
603 loc_copy_tags.push_back
604 (TagType{.dfab = this->
atLocalIdx(li).array(),
610 if (!maskfabs[li].isAllocated()) {
612 masks_unique.emplace_back(
Array4Tag<int>{.dfab = maskfabs[li].array()});
623 detail::fab_to_fab_atomic_cpy<value_type, value_type>(
624 loc_copy_tags, scomp, scomp, ncomp, masks);
632 auto const& LocTags = *(TheFB.
m_LocTags);
633 int N_locs = LocTags.size();
634 if (N_locs == 0) {
return; }
639 loc_copy_tags_1.reserve(N_locs);
640 loc_copy_tags_2.reserve(N_locs);
643 for (
int itag = 0; itag < N_locs; ++itag) {
645 src_fabs[itag].resize(tag.
sbox,ncomp);
646 loc_copy_tags_1.push_back(
647 TagType{.dfab = src_fabs[itag].array(), .dindex = -1,
649 .offset =
Dim3{.x = 0, .y = 0, .z = 0}});
650 loc_copy_tags_2.push_back(
652 .sfab = src_fabs[itag].const_array(), .dbox = tag.
dbox,
660 detail::fab_to_fab(loc_copy_tags_1, 0, 0, ncomp,
661 detail::CellStore<value_type, value_type>{});
663 detail::deterministic_fab_to_fab(loc_copy_tags_2, 0, 0, ncomp,
664 detail::CellAdd<value_type,value_type>{});
667 detail::fab_to_fab(loc_copy_tags_2, 0, 0, ncomp,
668 detail::CellAtomicAdd<value_type, value_type>{});
681 auto const& LocTags = *(thecmd.
m_LocTags);
682 int N_locs = LocTags.size();
683 if (N_locs == 0) {
return; }
688 loc_setval_tags.reserve(N_locs);
692 for (
int i = 0; i < N_locs; ++i)
696 loc_setval_tags.push_back(TagType{.dfab = this->
array(tag.
dstIndex), .dbox = tag.
dbox});
700 [
x,scomp]
AMREX_GPU_DEVICE (
int i,
int j,
int k,
int n, TagType
const& tag)
noexcept
702 tag.dfab(i,j,k,n+scomp) =
x;
711 auto const& RcvTags = *(thecmd.
m_RcvTags);
717 for (
auto it = RcvTags.begin(); it != RcvTags.end(); ++it) {
718 for (
auto const& tag: it->second) {
719 rcv_setval_tags.push_back(TagType{.dfab = this->
array(tag.dstIndex), .dbox = tag.dbox});
723 if (rcv_setval_tags.empty()) {
return; }
728 [
x,scomp]
AMREX_GPU_DEVICE (
int i,
int j,
int k,
int n, TagType
const& tag)
noexcept
730 tag.dfab(i,j,k,n+scomp) =
x;
734#if defined(__CUDACC__) && defined (AMREX_USE_CUDA)
739 const int N_locs = (*TheFB.m_LocTags).size();
741 for (
int i = 0; i < N_locs; ++i)
743 const CopyComTag& tag = (*TheFB.m_LocTags)[i];
748 loc_copy_tags[tag.dstIndex].push_back
749 ({this->fabPtr(tag.srcIndex), tag.dbox, tag.sbox.smallEnd()-tag.dbox.smallEnd()});
753 if ( !(TheFB.m_localCopy.ready()) )
755 const_cast<FB&
>(TheFB).m_localCopy.resize(N_locs);
761 amrex::Gpu::Device::startGraphRecording( (mfi.LocalIndex() == 0),
762 const_cast<FB&
>(TheFB).m_localCopy.getHostPtr(0),
763 (TheFB).m_localCopy.getDevicePtr(0),
764 std::size_t(
sizeof(CopyMemory)*N_locs) );
766 const auto& tags = loc_copy_tags[mfi];
767 for (
auto const & tag : tags)
769 const auto offset = tag.offset.dim3();
770 CopyMemory* cmem = TheFB.m_localCopy.getDevicePtr(idx++);
774 auto const dst = cmem->getDst<value_type>();
775 auto const src = cmem->getSrc<value_type>();
776 for (int n = 0; n < cmem->ncomp; ++n) {
777 dst(i,j,k,(cmem->scomp)+n) = src(i+offset.x,j+offset.y,k+offset.z,(cmem->scomp)+n);
782 bool last_iter = mfi.LocalIndex() == (this->local_size()-1);
783 cudaGraphExec_t graphExec = amrex::Gpu::Device::stopGraphRecording(last_iter);
784 if (last_iter) {
const_cast<FB&
>(TheFB).m_localCopy.setGraph( graphExec ); }
795 auto const dst_array = this->array(mfi);
796 const auto& tags = loc_copy_tags[mfi];
797 for (
auto const & tag : tags)
799 const_cast<FB&
>(TheFB).m_localCopy.setParams(idx++, makeCopyMemory(tag.sfab->array(),
806 TheFB.m_localCopy.executeGraph();
812FabArray<FAB>::FB_local_copy_cuda_graph_n (
const FB& TheFB,
int scomp,
int ncomp)
814 const int N_locs = TheFB.m_LocTags->size();
818 for (
int i = 0; i < N_locs; ++i)
820 const CopyComTag& tag = (*TheFB.m_LocTags)[i];
822 BL_ASSERT(ParallelDescriptor::sameTeam(distributionMap[tag.dstIndex]));
823 BL_ASSERT(ParallelDescriptor::sameTeam(distributionMap[tag.srcIndex]));
825 if (distributionMap[tag.dstIndex] == ParallelDescriptor::MyProc())
827 loc_copy_tags[tag.dstIndex].push_back
828 ({this->fabPtr(tag.srcIndex), tag.dbox, tag.sbox.smallEnd()-tag.dbox.smallEnd()});
835 if ( !(TheFB.m_localCopy.ready()) )
837 const_cast<FB&
>(TheFB).m_localCopy.resize(launches);
841 for (MFIter mfi(*
this, MFItInfo().DisableDeviceSync()); mfi.isValid(); ++mfi)
843 const auto& tags = loc_copy_tags[mfi];
844 for (
int t = 0; t<tags.size(); ++t)
846 Gpu::Device::setStreamIndex(cuda_stream++);
847 amrex::Gpu::Device::startGraphRecording( (idx == 0),
848 const_cast<FB&
>(TheFB).m_localCopy.getHostPtr(0),
849 (TheFB).m_localCopy.getDevicePtr(0),
850 std::size_t(
sizeof(CopyMemory)*launches) );
852 const auto& tag = tags[t];
853 const Dim3 offset = tag.offset.dim3();
855 CopyMemory* cmem = TheFB.m_localCopy.getDevicePtr(idx++);
858 auto const dst = cmem->getDst<value_type>();
859 auto const src = cmem->getSrc<value_type>();
860 for (int n = 0; n < cmem->ncomp; ++n) {
861 dst(i,j,k,(cmem->scomp)+n) = src(i+offset.x,j+offset.y,k+offset.z,(cmem->scomp)+n);
865 bool last_iter = idx == launches;
866 cudaGraphExec_t graphExec = Gpu::Device::stopGraphRecording(last_iter);
867 if (last_iter) {
const_cast<FB&
>(TheFB).m_localCopy.setGraph( graphExec ); }
875 for (MFIter mfi(*
this); mfi.isValid(); ++mfi)
877 const auto& dst_array = this->array(mfi);
878 const auto& tags = loc_copy_tags[mfi];
879 for (
auto const & tag : tags)
881 const_cast<FB&
>(TheFB).m_localCopy.setParams(idx++, makeCopyMemory(tag.sfab->array(),
888 TheFB.m_localCopy.executeGraph(
false);
900#if defined(__CUDACC__) && defined(AMREX_USE_CUDA)
904FabArray<FAB>::FB_pack_send_buffer_cuda_graph (
const FB& TheFB,
int scomp,
int ncomp,
905 Vector<char*>& send_data,
906 Vector<std::size_t>
const& send_size,
907 Vector<
typename FabArray<FAB>::CopyComTagsContainer
const*>
const& send_cctc)
909 const int N_snds = send_data.size();
910 if (N_snds == 0) {
return; }
912 if ( !(TheFB.m_copyToBuffer.ready()) )
917 for (
int send = 0; send < N_snds; ++send) {
918 if (send_size[send] > 0) {
919 launches += send_cctc[send]->size();
922 const_cast<FB&
>(TheFB).m_copyToBuffer.resize(launches);
926 for (Gpu::StreamIter sit(N_snds,Gpu::StreamItInfo().DisableDeviceSync());
927 sit.isValid(); ++sit)
929 amrex::Gpu::Device::startGraphRecording( (sit() == 0),
930 const_cast<FB&
>(TheFB).m_copyToBuffer.getHostPtr(0),
931 (TheFB).m_copyToBuffer.getDevicePtr(0),
932 std::size_t(
sizeof(CopyMemory)*launches) );
935 if (send_size[j] > 0)
937 auto const& cctc = *send_cctc[j];
938 for (
auto const& tag : cctc)
940 const Box& bx = tag.sbox;
941 CopyMemory* cmem = TheFB.m_copyToBuffer.getDevicePtr(idx++);
944 auto const pfab = cmem->getDst<value_type>();
945 auto const sfab = cmem->getSrc<value_type>();
946 for (
int n = 0; n < cmem->ncomp; ++n)
948 pfab(ii,jj,kk,n) = sfab(ii,jj,kk,n+(cmem->scomp));
954 bool last_iter = sit() == (N_snds-1);
955 cudaGraphExec_t graphExec = amrex::Gpu::Device::stopGraphRecording(last_iter);
956 if (last_iter) {
const_cast<FB&
>(TheFB).m_copyToBuffer.setGraph( graphExec ); }
962 for (
int send = 0; send < N_snds; ++send)
965 if (send_size[j] > 0)
967 char* dptr = send_data[j];
968 auto const& cctc = *send_cctc[j];
969 for (
auto const& tag : cctc)
971 const_cast<FB&
>(TheFB).m_copyToBuffer.setParams(idx++, makeCopyMemory(this->array(tag.srcIndex),
977 dptr += (tag.sbox.numPts() * ncomp *
sizeof(value_type));
980 BL_ASSERT(dptr <= send_data[j] + send_size[j]);
985 TheFB.m_copyToBuffer.executeGraph();
990FabArray<FAB>::FB_unpack_recv_buffer_cuda_graph (
const FB& TheFB,
int dcomp,
int ncomp,
991 Vector<char*>
const& recv_data,
992 Vector<std::size_t>
const& recv_size,
993 Vector<CopyComTagsContainer const*>
const& recv_cctc,
996 const int N_rcvs = recv_cctc.size();
997 if (N_rcvs == 0) {
return; }
1001 for (
int k = 0; k < N_rcvs; ++k)
1003 if (recv_size[k] > 0)
1005 const char* dptr = recv_data[k];
1006 auto const& cctc = *recv_cctc[k];
1007 for (
auto const& tag : cctc)
1009 recv_copy_tags[tag.dstIndex].push_back(VoidCopyTag{.p = dptr, .dbox = tag.dbox});
1010 dptr += tag.dbox.numPts() * ncomp *
sizeof(value_type);
1014 BL_ASSERT(dptr <= recv_data[k] + recv_size[k]);
1018 if ( !(TheFB.m_copyFromBuffer.ready()) )
1020 const_cast<FB&
>(TheFB).m_copyFromBuffer.resize(launches);
1023 for (MFIter mfi(*
this, MFItInfo().DisableDeviceSync()); mfi.isValid(); ++mfi)
1025 amrex::Gpu::Device::startGraphRecording( (mfi.LocalIndex() == 0),
1026 const_cast<FB&
>(TheFB).m_copyFromBuffer.getHostPtr(0),
1027 (TheFB).m_copyFromBuffer.getDevicePtr(0),
1028 std::size_t(
sizeof(CopyMemory)*launches) );
1030 const auto& tags = recv_copy_tags[mfi];
1031 for (
auto const & tag : tags)
1033 CopyMemory* cmem = TheFB.m_copyFromBuffer.getDevicePtr(idx++);
1036 auto const pfab = cmem->getSrc<value_type>();
1037 auto const dfab = cmem->getDst<value_type>();
1038 for (int n = 0; n < cmem->ncomp; ++n)
1040 dfab(i,j,k,n+(cmem->scomp)) = pfab(i,j,k,n);
1045 bool last_iter = mfi.LocalIndex() == (this->local_size()-1);
1046 cudaGraphExec_t graphExec = amrex::Gpu::Device::stopGraphRecording(last_iter);
1047 if (last_iter) {
const_cast<FB&
>(TheFB).m_copyFromBuffer.setGraph( graphExec ); }
1053 for (MFIter mfi(*
this); mfi.isValid(); ++mfi)
1055 auto dst_array = this->array(mfi);
1056 const auto & tags = recv_copy_tags[mfi];
1057 for (
auto const & tag : tags)
1059 const_cast<FB&
>(TheFB).m_copyFromBuffer.setParams(idx++, makeCopyMemory(
amrex::makeArray4((value_type*)(tag.p),
1068 TheFB.m_copyFromBuffer.executeGraph();
1074template <
typename BUF>
1079 int ncomp, std::uint64_t
id)
const
1084 auto kit = std::find_if(send_cctc.begin(), send_cctc.end(),
1086 if (kit == send_cctc.end()) {
1093 char* pbuf = send_data[0];
1094 const int N_snds = send_data.
size();
1095 for (
int j = 0; j < N_snds; ++j)
1097 if (send_size[j] > 0)
1099 char* dptr = send_data[j];
1100 auto const& cctc = *send_cctc[j];
1101 for (
auto const& tag : cctc)
1103 snd_copy_tags.emplace_back
1104 (TagType{.sfab = this->
const_array(tag.srcIndex), .poff = dptr-pbuf, .bx = tag.sbox});
1105 dptr += (tag.sbox.numPts() * ncomp *
sizeof(BUF));
1109 return snd_copy_tags;
1113 std::tuple<std::uint64_t,std::size_t,int> key{id,
sizeof(BUF), ncomp};
1115 if (
auto it = m_send_copy_handler.find(key); it != m_send_copy_handler.end()) {
1116 tv = it->second.get();
1118 if (m_send_copy_handler.size() > 32) {
1123 m_send_copy_handler.clear();
1125 auto snd_copy_tags = get_tags();
1126 auto utv = std::make_unique<TagVector<TagType>>(snd_copy_tags);
1128 m_send_copy_handler[key] = std::move(utv);
1135template <
typename BUF>
1143 const int N_snds = send_data.
size();
1144 if (N_snds == 0) {
return; }
1149 (send_data, send_size, send_cctc, ncomp,
id);
1150 if (tv ==
nullptr) {
return; }
1152 char* pbuffer = send_data[0];
1154 detail::ParallelFor_doit(*tv,
1156 int icell,
int ncells,
int i,
int j,
int k, TagType
const& tag)
noexcept
1158 if (icell < ncells) {
1161 for (
int n = 0; n < ncomp; ++n) {
1162 dfab(i,j,k,n) = (BUF)tag.sfab(i,j,k,n+scomp);
1171template <
typename BUF>
1176 int ncomp, std::uint64_t
id)
1181 auto kit = std::find_if(recv_cctc.begin(), recv_cctc.end(),
1183 if (kit == recv_cctc.end()) {
1190 char* pbuf = recv_data[0];
1191 const int N_rcvs = recv_cctc.
size();
1192 for (
int k = 0; k < N_rcvs; ++k)
1194 if (recv_size[k] > 0)
1196 char* dptr = recv_data[k];
1197 auto const& cctc = *recv_cctc[k];
1198 for (
auto const& tag : cctc)
1200 const int li = this->
localindex(tag.dstIndex);
1201 recv_copy_tags.emplace_back
1202 (TagType{.dfab = this->
atLocalIdx(li).array(), .poff = dptr-pbuf, .bx = tag.dbox});
1203 dptr += tag.dbox.numPts() * ncomp *
sizeof(BUF);
1207 return recv_copy_tags;
1211 std::tuple<std::uint64_t,std::size_t,int> key{id,
sizeof(BUF), ncomp};
1213 if (
auto it = m_recv_copy_handler.find(key); it != m_recv_copy_handler.end()) {
1214 tv = it->second.get();
1216 if (m_recv_copy_handler.size() > 32) {
1221 m_recv_copy_handler.clear();
1223 auto recv_copy_tags = get_tags();
1224 auto utv = std::make_unique<TagVector<TagType>>(recv_copy_tags);
1226 m_recv_copy_handler[key] = std::move(utv);
1233template <
typename BUF>
1239 CpOp op,
bool is_thread_safe, std::uint64_t
id,
1242 const int N_rcvs = recv_cctc.
size();
1243 if (N_rcvs == 0) {
return; }
1246 if (!is_thread_safe)
1260 tags.reserve(N_rcvs);
1261 for (
int k = 0; k < N_rcvs; ++k) {
1262 if (recv_size[k] > 0) {
1263 char const* dptr = recv_data[k];
1264 auto const& cctc = *recv_cctc[k];
1265 for (
auto const& tag : cctc) {
1267 TagType{.dfab = dst.
array(tag.dstIndex), .dindex = tag.dstIndex,
1272 .offset =
Dim3{.x = 0, .y = 0, .z = 0}});
1273 dptr += tag.dbox.numPts() * ncomp *
sizeof(BUF);
1278 detail::deterministic_fab_to_fab<value_type,BUF>
1279 (
tags, 0, dcomp, ncomp, detail::CellAdd<value_type,BUF>{});
1288 (recv_data, recv_size, recv_cctc, ncomp,
id);
1289 if (tv ==
nullptr) {
return; }
1291 char* pbuffer = recv_data[0];
1295 detail::ParallelFor_doit(*tv,
1297 int icell,
int ncells,
int i,
int j,
int k, TagType
const& tag)
noexcept
1299 if (icell < ncells) {
1302 for (
int n = 0; n < ncomp; ++n) {
1303 tag.dfab(i,j,k,n+dcomp) = (
value_type)sfab(i,j,k,n);
1310 if (is_thread_safe) {
1311 detail::ParallelFor_doit(*tv,
1313 int icell,
int ncells,
int i,
int j,
int k, TagType
const& tag)
noexcept
1315 if (icell < ncells) {
1318 for (
int n = 0; n < ncomp; ++n) {
1319 tag.dfab(i,j,k,n+dcomp) += (
value_type)sfab(i,j,k,n);
1324 detail::unpack_recv_buffer_gpu_atomic_add<BUF, value_type>
1325 (pbuffer, *tv, dcomp, ncomp);
1332 char* pbuffer = recv_data[0];
1336 recv_copy_tags.reserve(N_rcvs);
1343 for (
int k = 0; k < N_rcvs; ++k)
1345 if (recv_size[k] > 0)
1347 std::size_t offset = recv_data[k]-recv_data[0];
1348 const char* dptr = pbuffer + offset;
1349 auto const& cctc = *recv_cctc[k];
1350 for (
auto const& tag : cctc)
1353 recv_copy_tags.emplace_back(TagType{
1354 .dfab = dst.
atLocalIdx(li).array(), .dindex = tag.dstIndex,
1357 .offset =
Dim3{.x = 0, .y = 0, .z = 0}
1359 dptr += tag.dbox.numPts() * ncomp *
sizeof(BUF);
1361 if (!maskfabs[li].isAllocated()) {
1362 maskfabs[li].resize(dst.
atLocalIdx(li).box());
1363 masks_unique.emplace_back(
Array4Tag<int>{.dfab = maskfabs[li].array()});
1365 masks.emplace_back(
Array4Tag<int>{.dfab = maskfabs[li].array()});
1367 BL_ASSERT(dptr <= pbuffer + offset + recv_size[k]);
1374 msk.
dfab(i,j,k) = 0;
1379 detail::fab_to_fab_atomic_cpy<value_type, BUF>(
1380 recv_copy_tags, 0, dcomp, ncomp, masks);
1384 detail::fab_to_fab_atomic_add<value_type, BUF>(
1385 recv_copy_tags, 0, dcomp, ncomp, masks);
1395template <
typename BUF>
1404 auto const N_snds =
static_cast<int>(send_data.
size());
1405 if (N_snds == 0) {
return; }
1408 if (omp_get_max_threads() > 1)
1412 for (
int j = 0; j < N_snds; ++j)
1414 if (send_size[j] > 0)
1416 char* dptr = send_data[j];
1417 for (
auto const& tag : *send_cctc[j])
1419 tags.emplace_back(dptr, &tag);
1420 dptr += (tag.sbox.numPts() * ncomp *
sizeof(BUF));
1422 BL_ASSERT(dptr <= send_data[j] + send_size[j]);
1426 auto const N_tags =
static_cast<int>(
tags.size());
1428 int const chunk = std::clamp(N_tags/omp_get_max_threads(), 1, 64);
1429#pragma omp parallel for schedule(static,chunk)
1430 for (
int i = 0; i < N_tags; ++i)
1432 auto const& tag = *
tags[i].second;
1433 const Box& bx = tag.sbox;
1434 auto const sfab = src.
array(tag.srcIndex);
1437 [=] (
int ii,
int jj,
int kk,
int n)
noexcept
1439 pfab(ii,jj,kk,n) =
static_cast<BUF
>(sfab(ii,jj,kk,n+scomp));
1446 for (
int j = 0; j < N_snds; ++j)
1448 if (send_size[j] > 0)
1450 char* dptr = send_data[j];
1451 auto const& cctc = *send_cctc[j];
1452 for (
auto const& tag : cctc)
1454 const Box& bx = tag.sbox;
1455 auto const sfab = src.
array(tag.srcIndex);
1458 [=] (
int ii,
int jj,
int kk,
int n)
noexcept
1460 pfab(ii,jj,kk,n) =
static_cast<BUF
>(sfab(ii,jj,kk,n+scomp));
1462 dptr += (bx.
numPts() * ncomp *
sizeof(BUF));
1464 BL_ASSERT(dptr <= send_data[j] + send_size[j]);
1470template <
typename BUF>
1476 CpOp op,
bool is_thread_safe)
1480 auto const N_rcvs =
static_cast<int>(recv_cctc.
size());
1481 if (N_rcvs == 0) {
return; }
1486 if (omp_get_max_threads() > 1)
1490 for (
int k = 0; k < N_rcvs; ++k)
1492 if (recv_size[k] > 0)
1494 const char* dptr = recv_data[k];
1495 for (
auto const& tag : *recv_cctc[k])
1497 tags.emplace_back(dptr, &tag);
1498 dptr += tag.dbox.numPts() * ncomp *
sizeof(BUF);
1500 BL_ASSERT(dptr <= recv_data[k] + recv_size[k]);
1504 auto const N_tags =
static_cast<int>(
tags.size());
1506 int const chunk = std::clamp(N_tags/omp_get_max_threads(), 1, 64);
1507#pragma omp parallel for schedule(static,chunk)
1508 for (
int i = 0; i < N_tags; ++i)
1510 auto const& tag = *
tags[i].second;
1511 FAB& dfab = dst[tag.dstIndex];
1514 dfab.template copyFromMem<RunOn::Host, BUF>(tag.dbox, dcomp, ncomp,
tags[i].first);
1518 dfab.template addFromMem<RunOn::Host, BUF>(tag.dbox, dcomp, ncomp,
tags[i].first);
1525 for (
int k = 0; k < N_rcvs; ++k)
1527 if (recv_size[k] > 0)
1529 const char* dptr = recv_data[k];
1530 auto const& cctc = *recv_cctc[k];
1531 for (
auto const& tag : cctc)
1533 const Box& bx = tag.dbox;
1534 FAB& dfab = dst[tag.dstIndex];
1537 dfab.template copyFromMem<RunOn::Host, BUF>(bx, dcomp, ncomp, dptr);
1541 dfab.template addFromMem<RunOn::Host, BUF>(tag.dbox, dcomp, ncomp, dptr);
1543 dptr += bx.
numPts() * ncomp *
sizeof(BUF);
1545 BL_ASSERT(dptr <= recv_data[k] + recv_size[k]);
1553 for (
int k = 0; k < N_rcvs; ++k)
1555 if (recv_size[k] > 0)
1557 const char* dptr = recv_data[k];
1558 auto const& cctc = *recv_cctc[k];
1559 for (
auto const& tag : cctc)
1561 recv_copy_tags[tag.dstIndex].push_back(
VoidCopyTag{.p = dptr, .dbox = tag.dbox});
1562 dptr += tag.dbox.numPts() * ncomp *
sizeof(BUF);
1564 BL_ASSERT(dptr <= recv_data[k] + recv_size[k]);
1571 for (
MFIter mfi(dst); mfi.isValid(); ++mfi)
1573 const auto&
tags = recv_copy_tags[mfi];
1574 auto dfab = dst.
array(mfi);
1575 for (
auto const & tag :
tags)
1581 [=] (
int i,
int j,
int k,
int n)
noexcept
1583 dfab(i,j,k,n+dcomp) = pfab(i,j,k,n);
1589 [=] (
int i,
int j,
int k,
int n)
noexcept
1591 dfab(i,j,k,n+dcomp) += pfab(i,j,k,n);
#define BL_ASSERT(EX)
Definition AMReX_BLassert.H:39
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_FORCE_INLINE
Definition AMReX_Extension.H:124
#define AMREX_HOST_DEVICE_FOR_3D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:106
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
while parser_exe_t p
Definition AMReX_Parser_Exe_Body.H:33
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
__host__ __device__ Long numPts() const noexcept
Return the number of points contained in the BoxND.
Definition AMReX_Box.H:385
__host__ __device__ const IntVectND< dim > & smallEnd() const &noexcept
Return the inclusive lower bound of the box.
Definition AMReX_Box.H:124
friend class MFIter
Definition AMReX_FabArrayBase.H:48
CopyComTag::CopyComTagsContainer CopyComTagsContainer
Definition AMReX_FabArrayBase.H:236
int localindex(int K) const noexcept
Return local index in the vector of FABs.
Definition AMReX_FabArrayBase.H:124
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:135
int local_size() const noexcept
Return the number of local FABs in the FabArray.
Definition AMReX_FabArrayBase.H:118
CpOp
parallel copy or add
Definition AMReX_FabArrayBase.H:424
@ ADD
Definition AMReX_FabArrayBase.H:424
@ COPY
Definition AMReX_FabArrayBase.H:424
Box box(int K) const noexcept
Return the Kth Box in the BoxArray. That is, the valid region of the Kth grid.
Definition AMReX_FabArrayBase.H:106
DistributionMapping distributionMap
Definition AMReX_FabArrayBase.H:528
const BoxArray & boxArray() const noexcept
Return a constant reference to the BoxArray that defines the valid region associated with this FabArr...
Definition AMReX_FabArrayBase.H:100
An Array of FortranArrayBox(FAB)-like Objects.
Definition AMReX_FabArray.H:356
TagVector< CommSendBufTag< value_type > > const * get_send_copy_tag_vector(Vector< char * > const &send_data, Vector< std::size_t > const &send_size, Vector< CopyComTagsContainer const * > const &send_cctc, int ncomp, std::uint64_t id) const
typename std::conditional_t< IsBaseFab< FAB >::value, FAB, FABType >::value_type value_type
Definition AMReX_FabArray.H:367
void CMD_remote_setVal_gpu(value_type x, const CommMetaData &thecmd, int scomp, int ncomp)
Definition AMReX_FBI.H:708
static void unpack_recv_buffer_gpu(FabArray< FAB > &dst, int dcomp, int ncomp, Vector< char * > const &recv_data, Vector< std::size_t > const &recv_size, Vector< const CopyComTagsContainer * > const &recv_cctc, CpOp op, bool is_thread_safe, std::uint64_t id, bool deterministic)
void FB_local_add_cpu(const FB &TheFB, int scomp, int ncomp)
Definition AMReX_FBI.H:467
static void unpack_recv_buffer_cpu(FabArray< FAB > &dst, int dcomp, int ncomp, Vector< char * > const &recv_data, Vector< std::size_t > const &recv_size, Vector< const CopyComTagsContainer * > const &recv_cctc, CpOp op, bool is_thread_safe)
void FB_local_add_gpu(const FB &TheFB, int scomp, int ncomp, bool deterministic)
Definition AMReX_FBI.H:630
void FB_local_copy_gpu(const FB &TheFB, int scomp, int ncomp)
Definition AMReX_FBI.H:558
void copy(const FabArray< FAB > &src, const Periodicity &period=Periodicity::NonPeriodic(), CpOp op=FabArrayBase::COPY)
Definition AMReX_FabArray.H:977
const Vector< std::string > & tags() const noexcept
Memory-usage tags recorded for this FabArray's allocations.
Definition AMReX_FabArray.H:488
void CMD_local_setVal_gpu(value_type x, const CommMetaData &thecmd, int scomp, int ncomp)
Definition AMReX_FBI.H:678
static void pack_send_buffer_gpu(FabArray< FAB > const &src, int scomp, int ncomp, Vector< char * > const &send_data, Vector< std::size_t > const &send_size, Vector< const CopyComTagsContainer * > const &send_cctc, std::uint64_t id)
Array4< typename FabArray< FAB >::value_type const > array(const MFIter &mfi) const noexcept
Read-only Array4 view for the FAB referenced by iterator mfi.
Definition AMReX_FabArray.H:621
void FB_local_copy_cpu(const FB &TheFB, int scomp, int ncomp)
Definition AMReX_FBI.H:396
TagVector< Array4CopyTag< value_type > > const * FB_get_local_copy_tag_vector(const FB &TheFB)
Definition AMReX_FBI.H:515
static void pack_send_buffer_cpu(FabArray< FAB > const &src, int scomp, int ncomp, Vector< char * > const &send_data, Vector< std::size_t > const &send_size, Vector< const CopyComTagsContainer * > const &send_cctc)
FAB * fabPtr(const MFIter &mfi) noexcept
Return pointer to FAB.
Definition AMReX_FabArray.H:2065
TagVector< CommRecvBufTag< value_type > > const * get_recv_copy_tag_vector(Vector< char * > const &recv_data, Vector< std::size_t > const &recv_size, Vector< CopyComTagsContainer const * > const &recv_cctc, int ncomp, std::uint64_t id)
FAB & atLocalIdx(int L) noexcept
Return a reference to the FAB associated with local index L.
Definition AMReX_FabArray.H:579
Array4< typename FabArray< FAB >::value_type const > const_array(const MFIter &mfi) const noexcept
Synonym for array(const MFIter&) that highlights read-only semantics.
Definition AMReX_FabArray.H:649
a one-thingy-per-box distributed object
Definition AMReX_LayoutData.H:13
void define(const BoxArray &a_grids, const DistributionMapping &a_dm)
Definition AMReX_LayoutData.H:24
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
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
__host__ __device__ Dim3 length(Array4< T > const &a) noexcept
Return the spatial extents of an Array4 in Dim3 form.
Definition AMReX_Array4.H:1379
ArrayND< T, 4, true > Array4
Convenient alias for a 4D ArrayND with three spatial dimensions plus a component dimension.
Definition AMReX_Array4.H:1340
__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 > coarsen(const BoxND< dim > &b, int ref_ratio) noexcept
Return a copy of b coarsened by the isotropic ratio ref_ratio.
Definition AMReX_Box.H:1471
PinnedVector< T > HostVector
A PODVector that uses pinned host memory. Same as PinnedVector. For a vector class that uses std::all...
Definition AMReX_GpuContainers.H:67
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
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
__host__ __device__ AMREX_FORCE_INLINE T Exch(T *address, T val) noexcept
Definition AMReX_GpuAtomic.H:487
__host__ __device__ AMREX_FORCE_INLINE T CAS(T *const address, T compare, T const val) noexcept
Definition AMReX_GpuAtomic.H:513
__host__ __device__ AMREX_FORCE_INLINE void AddNoRet(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:283
__host__ __device__ AMREX_FORCE_INLINE T Add(T *sum, T value) noexcept
Definition AMReX_GpuAtomic.H:200
void copyAsync(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:228
static constexpr HostToDevice hostToDevice
Definition AMReX_GpuContainers.H:105
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:329
gpuStream_t gpuStream() noexcept
Definition AMReX_GpuDevice.H:310
bool sameTeam(int rank) noexcept
Definition AMReX_ParallelDescriptor.H:345
int TeamSize() noexcept
Definition AMReX_ParallelDescriptor.H:310
const ProcessTeam & MyTeam() noexcept
Definition AMReX_ParallelDescriptor.H:365
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
__host__ __device__ Array4< T > makeArray4(T *p, Box const &bx, int ncomp) noexcept
Definition AMReX_BaseFab.H:123
BoxArray const & boxArray(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.boxArray().
Definition AMReX_FabArrayBase.cpp:2990
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.DistributionMap().
Definition AMReX_FabArrayBase.cpp:2995
__host__ __device__ Dim3 begin(BoxND< dim > const &box) noexcept
Return the iterator begin coordinate of box as Dim3.
Definition AMReX_Box.H:2241
bool NeighborParticleContainer_impl< T_ParticleType, NArrayReal, NArrayInt, Allocator, CellAssignor >::use_mask
Definition AMReX_NeighborParticlesI.H:13
void launch(T const &n, L const &f) noexcept
Definition AMReX_GpuLaunchFunctsC.H:122
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
@ x
Definition AMReX_Orientation.H:14
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
void LoopConcurrentOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:388
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
const int[]
Definition AMReX_BLProfiler.cpp:1665
__host__ __device__ Dim3 end(BoxND< dim > const &box) noexcept
Return the iterator end coordinate of box as Dim3.
Definition AMReX_Box.H:2259
__host__ __device__ constexpr int get(IntVectND< dim > const &iv) noexcept
Get the Idx-th element of IntVectND<dim>.
Definition AMReX_IntVect.H:1360
Definition AMReX_TagParallelFor.H:58
Definition AMReX_TagParallelFor.H:26
Definition AMReX_TagParallelFor.H:50
Array4< T > dfab
Definition AMReX_TagParallelFor.H:51
Definition AMReX_TagParallelFor.H:106
Definition AMReX_TagParallelFor.H:116
A simple struct holding 3 int values for a 3D index.
Definition AMReX_Dim3.H:24
Used by a bunch of routines when communicating via MPI.
Definition AMReX_FabArrayBase.H:211
Box sbox
Definition AMReX_FabArrayBase.H:213
int srcIndex
Definition AMReX_FabArrayBase.H:215
Box dbox
Definition AMReX_FabArrayBase.H:212
int dstIndex
Definition AMReX_FabArrayBase.H:214
FillBoundary.
Definition AMReX_FabArrayBase.H:580
Describes a source FAB region participating in a copy.
Definition AMReX_FBI.H:18
IntVect offset
Definition AMReX_FBI.H:21
Box dbox
Definition AMReX_FBI.H:20
FAB const * sfab
Definition AMReX_FBI.H:19
Definition AMReX_TypeTraits.H:51
Definition AMReX_TypeTraits.H:61
Definition AMReX_TypeTraits.H:277
Definition AMReX_MFIter.H:20
void MemoryBarrier() const
memory fence
Definition AMReX_ParallelDescriptor.H:161
Definition AMReX_TagParallelFor.H:156
Lightweight tag describing raw pointer copies (used for pack/unpack).
Definition AMReX_FBI.H:25
Box dbox
Definition AMReX_FBI.H:27
char const * p
Definition AMReX_FBI.H:26