Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_PCI.H
Go to the documentation of this file.
1#ifndef AMREX_PCI_H_
2#define AMREX_PCI_H_
3
4namespace amrex {
5
6template <class FAB>
7void
8FabArray<FAB>::PC_local_cpu (const CPC& thecpc, FabArray<FAB> const& src,
9 int scomp, int dcomp, int ncomp, CpOp op)
10{
11 auto const N_locs = static_cast<int>(thecpc.m_LocTags->size());
12 if (N_locs == 0) { return; }
13 bool is_thread_safe = thecpc.m_threadsafe_loc;
14
15 if (is_thread_safe)
16 {
17#ifdef AMREX_USE_OMP
18#pragma omp parallel for
19#endif
20 for (int i = 0; i < N_locs; ++i)
21 {
22 const CopyComTag& tag = (*thecpc.m_LocTags)[i];
23#ifdef BL_USE_TEAM
24 // With MPI teams, the tags include teammates' FABs. Only write our own.
25 if (distributionMap[tag.dstIndex] != ParallelDescriptor::MyProc()) { continue; }
26#endif
27 if (this != &src || tag.dstIndex != tag.srcIndex || tag.sbox != tag.dbox) {
28 // avoid self copy or plus
29 const FAB* sfab = &(src[tag.srcIndex]);
30 FAB* dfab = &(get(tag.dstIndex));
31 if (op == FabArrayBase::COPY)
32 {
33 dfab->template copy<RunOn::Host>(*sfab, tag.sbox, scomp, tag.dbox, dcomp, ncomp);
34 }
35 else
36 {
37 dfab->template plus<RunOn::Host>(*sfab, tag.sbox, tag.dbox, scomp, dcomp, ncomp);
38 }
39 }
40 }
41#ifdef BL_USE_TEAM
42 // Teammates may read our FABs next.
44#endif
45 }
46 else
47 {
49 for (int i = 0; i < N_locs; ++i)
50 {
51 const CopyComTag& tag = (*thecpc.m_LocTags)[i];
52 if (this != &src || tag.dstIndex != tag.srcIndex || tag.sbox != tag.dbox) {
53 loc_copy_tags[tag.dstIndex].push_back
54 ({src.fabPtr(tag.srcIndex), tag.dbox, tag.sbox.smallEnd()-tag.dbox.smallEnd()});
55 }
56 }
57
58#ifdef AMREX_USE_OMP
59#pragma omp parallel
60#endif
61 for (MFIter mfi(*this); mfi.isValid(); ++mfi)
62 {
63 const auto& tags = loc_copy_tags[mfi];
64 auto dfab = this->array(mfi);
65 if (op == FabArrayBase::COPY)
66 {
67 for (auto const & tag : tags)
68 {
69 auto const sfab = tag.sfab->array();
70 Dim3 offset = tag.offset.dim3();
71 amrex::LoopConcurrentOnCpu (tag.dbox, ncomp,
72 [=] (int i, int j, int k, int n) noexcept
73 {
74 dfab(i,j,k,dcomp+n) = sfab(i+offset.x,j+offset.y,k+offset.z,scomp+n);
75 });
76 }
77 }
78 else
79 {
80 for (auto const & tag : tags)
81 {
82 auto const sfab = tag.sfab->array();
83 Dim3 offset = tag.offset.dim3();
84 amrex::LoopConcurrentOnCpu (tag.dbox, ncomp,
85 [=] (int i, int j, int k, int n) noexcept
86 {
87 dfab(i,j,k,dcomp+n) += sfab(i+offset.x,j+offset.y,k+offset.z,scomp+n);
88 });
89 }
90 }
91 }
92 }
93}
94
95#ifdef AMREX_USE_GPU
96template <class FAB>
97void
99 int scomp, int dcomp, int ncomp, CpOp op,
100 bool deterministic)
101{
102 auto const N_locs = static_cast<int>(thecpc.m_LocTags->size());
103 if (N_locs == 0) { return; }
104 bool is_thread_safe = thecpc.m_threadsafe_loc;
105
106 // Deterministic handling is only implemented for ADD.
107 if (deterministic) { AMREX_ALWAYS_ASSERT(op == FabArrayBase::ADD); }
108
109 using TagType = Array4CopyTag<value_type>;
110 Vector<TagType> loc_copy_tags;
111 loc_copy_tags.reserve(N_locs);
112
113 Vector<BaseFab<int> > maskfabs;
114 Vector<Array4Tag<int> > masks_unique;
115 Vector<Array4Tag<int> > masks;
116 if (!is_thread_safe)
117 {
119 (op == FabArrayBase::ADD && !amrex::HasAtomicAdd <value_type>::value &&
120 !deterministic))
121 {
122 maskfabs.resize(this->local_size());
123 masks_unique.reserve(this->local_size());
124 masks.reserve(N_locs);
125 }
126 }
127
128 for (int i = 0; i < N_locs; ++i)
129 {
130 const CopyComTag& tag = (*thecpc.m_LocTags)[i];
131 if (this != &src || tag.dstIndex != tag.srcIndex || tag.sbox != tag.dbox) {
132 int li = this->localindex(tag.dstIndex);
133 loc_copy_tags.push_back(
134 TagType{.dfab = this->atLocalIdx(li).array(),
135 .dindex = tag.dstIndex,
136 .sfab = src.fabPtr(tag.srcIndex)->const_array(),
137 .dbox = tag.dbox,
138 .offset = (tag.sbox.smallEnd()-tag.dbox.smallEnd()).dim3()});
139
140 if (maskfabs.size() > 0) {
141 if (!maskfabs[li].isAllocated()) {
142 maskfabs[li].resize(this->atLocalIdx(li).box());
143 masks_unique.emplace_back(Array4Tag<int>{.dfab = maskfabs[li].array()});
144 }
145 masks.emplace_back(Array4Tag<int>{.dfab = maskfabs[li].array()});
146 }
147 }
148 }
149
150 if (maskfabs.size() > 0) {
151 amrex::ParallelFor(masks_unique,
152 [=] AMREX_GPU_DEVICE (int i, int j, int k, Array4Tag<int> const& msk) noexcept
153 {
154 msk.dfab(i,j,k) = 0;
155 });
156 }
157
158 if (op == FabArrayBase::COPY)
159 {
160 if (is_thread_safe) {
161 detail::fab_to_fab<value_type, value_type>(loc_copy_tags, scomp,
162 dcomp, ncomp, detail::CellStore<value_type, value_type>());
163 } else {
164 detail::fab_to_fab_atomic_cpy<value_type, value_type>(
165 loc_copy_tags, scomp, dcomp, ncomp, masks);
166 }
167 }
168 else
169 {
170 if (is_thread_safe) {
171 // Non-overlapping destinations: a plain add is already bitwise
172 // reproducible, so no need for the heavier deterministic kernel.
173 detail::fab_to_fab<value_type, value_type>(loc_copy_tags, scomp,
174 dcomp, ncomp, detail::CellAdd<value_type, value_type>());
175 } else if (deterministic) {
176 // Use deterministic_fab_to_fab for ADD operations to ensure bitwise
177 // reproducibility. The atomic add operations (fab_to_fab_atomic_add) are
178 // non-deterministic because the order of atomic additions is not guaranteed.
179 detail::deterministic_fab_to_fab<value_type, value_type>(
180 loc_copy_tags, scomp, dcomp, ncomp, detail::CellAdd<value_type, value_type>());
181 } else {
182 detail::fab_to_fab_atomic_add<value_type, value_type>(
183 loc_copy_tags, scomp, dcomp, ncomp, masks);
184 }
185 }
186}
187#endif
188
189}
190
191#endif
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
__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
int localindex(int K) const noexcept
Return local index in the vector of FABs.
Definition AMReX_FabArrayBase.H:124
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
void PC_local_cpu(const CPC &thecpc, FabArray< FAB > const &src, int scomp, int dcomp, int ncomp, CpOp op)
Definition AMReX_PCI.H:8
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
FabArray() noexcept
Constructs an empty FabArray<FAB>.
Definition AMReX_FabArray.H:2327
void plus(value_type val, int comp, int num_comp, int nghost=0)
Definition AMReX_FabArray.H:3182
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 PC_local_gpu(const CPC &thecpc, FabArray< FAB > const &src, int scomp, int dcomp, int ncomp, CpOp op, bool deterministic)
Definition AMReX_PCI.H:98
FAB * fabPtr(const MFIter &mfi) noexcept
Return pointer to FAB.
Definition AMReX_FabArray.H:2065
FAB & atLocalIdx(int L) noexcept
Return a reference to the FAB associated with local index L.
Definition AMReX_FabArray.H:579
a one-thingy-per-box distributed object
Definition AMReX_LayoutData.H:13
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
int MyProc() noexcept
Definition AMReX_ParallelDescriptor.H:128
int TeamSize() noexcept
Definition AMReX_ParallelDescriptor.H:310
const ProcessTeam & MyTeam() noexcept
Definition AMReX_ParallelDescriptor.H:365
Definition AMReX_Amr.cpp:50
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
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
void LoopConcurrentOnCpu(Dim3 lo, Dim3 hi, F const &f) noexcept
Definition AMReX_Loop.H:388
__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:26
Definition AMReX_TagParallelFor.H:50
Array4< T > dfab
Definition AMReX_TagParallelFor.H:51
A simple struct holding 3 int values for a 3D index.
Definition AMReX_Dim3.H:24
parallel copy or add
Definition AMReX_FabArrayBase.H:643
bool m_threadsafe_loc
Definition AMReX_FabArrayBase.H:557
std::unique_ptr< CopyComTagsContainer > m_LocTags
Definition AMReX_FabArrayBase.H:559
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
Definition AMReX_TypeTraits.H:277
void MemoryBarrier() const
memory fence
Definition AMReX_ParallelDescriptor.H:161