QMCPACK
RealSpacePositionsOMPTarget.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 /** @file RealSpacePostionsOMPTarget.h
14  */
15 #ifndef QMCPLUSPLUS_REALSPACE_POSITIONS_OMPTARGET_H
16 #define QMCPLUSPLUS_REALSPACE_POSITIONS_OMPTARGET_H
17 
22 #include "ParticleSet.h"
23 #include "ResourceCollection.h"
24 
25 namespace qmcplusplus
26 {
27 /** Introduced to handle virtual moves and ratio computations, e.g. for non-local PP evaluations.
28  */
30 {
31 public:
34  {}
37  {
38  RSoA_hostview.attachReference(RSoA.size(), RSoA.capacity(), RSoA.data());
39  updateH2D();
40  }
41 
42  std::unique_ptr<DynamicCoordinates> makeClone() override
43  {
44  return std::make_unique<RealSpacePositionsOMPTarget>(*this);
45  }
46 
47  void resize(size_t n) override
48  {
49  if (RSoA.size() != n)
50  {
51  RSoA.resize(n);
52  RSoA_hostview.attachReference(RSoA.size(), RSoA.capacity(), RSoA.data());
53  }
54  }
55 
56  size_t size() const override { return RSoA_hostview.size(); }
57 
58  void setAllParticlePos(const ParticlePos& R) override
59  {
60  resize(R.size());
62  updateH2D();
63  is_nw_new_pos_prepared = false;
64  }
65 
66  void setOneParticlePos(const PosType& pos, size_t iat) override
67  {
68  RSoA_hostview(iat) = pos;
70  /* This was too slow due to overhead.
71  RealType x = pos[0];
72  RealType y = pos[1];
73  RealType z = pos[2];
74  RealType* data = RSoA.data();
75  size_t offset = RSoA.capacity();
76 
77  PRAGMA_OFFLOAD("omp target map(to : x, y, z, iat)")
78  {
79  data[iat] = x;
80  data[iat + offset] = y;
81  data[iat + offset * 2] = z;
82  }
83  */
84  }
85 
87  size_t iat,
88  const std::vector<PosType>& new_positions) const override
89  {
90  assert(this == &coords_list.getLeader());
91  auto& coords_leader = coords_list.getCastedLeader<RealSpacePositionsOMPTarget>();
92 
93  const auto nw = coords_list.size();
94  auto& mw_new_pos = coords_leader.mw_mem_handle_.getResource().mw_new_pos;
95  mw_new_pos.resize(nw);
96 
97  for (int iw = 0; iw < nw; iw++)
98  mw_new_pos(iw) = new_positions[iw];
99 
100  auto* mw_pos_ptr = mw_new_pos.data();
101  PRAGMA_OFFLOAD("omp target update to(mw_pos_ptr[:QMCTraits::DIM * mw_new_pos.capacity()])")
102 
103  coords_leader.is_nw_new_pos_prepared = true;
104  }
105 
107  size_t iat,
108  const std::vector<PosType>& new_positions,
109  const std::vector<bool>& isAccepted) const override
110  {
111  assert(this == &coords_list.getLeader());
112  const size_t nw = coords_list.size();
113  auto& coords_leader = coords_list.getCastedLeader<RealSpacePositionsOMPTarget>();
114  MultiWalkerMem& mw_mem = coords_leader.mw_mem_handle_;
115  auto& mw_new_pos = mw_mem.mw_new_pos;
116  auto& mw_rsoa_ptrs = mw_mem.mw_rsoa_ptrs;
117  auto& mw_accept_indices = mw_mem.mw_accept_indices;
118 
120  {
121  mw_copyActivePos(coords_list, iat, new_positions);
122  app_warning() << "This message only appear in unit tests. Report a bug if seen in production code." << std::endl;
123  }
124 
125  coords_leader.is_nw_new_pos_prepared = false;
126 
127  mw_accept_indices.resize(nw);
128  auto* restrict id_array = mw_accept_indices.data();
129 
130  size_t num_accepted = 0;
131  for (int iw = 0; iw < nw; iw++)
132  if (isAccepted[iw])
133  {
134  auto& coords = coords_list.getCastedElement<RealSpacePositionsOMPTarget>(iw);
135  id_array[num_accepted] = iw;
136  // save new coordinates on host copy
137  coords.RSoA_hostview(iat) = mw_new_pos[iw];
138  num_accepted++;
139  }
140 
141  // early return to avoid OpenMP runtime mishandling of size 0 in transfer/compute.
142  if (num_accepted == 0)
143  return;
144 
145  //offload to GPU
146  auto* restrict mw_pos_ptr = mw_new_pos.data();
147  auto* restrict mw_rosa_ptr = mw_rsoa_ptrs.data();
148  const size_t rsoa_stride = RSoA.capacity();
149  const size_t mw_pos_stride = mw_new_pos.capacity();
150 
151  PRAGMA_OFFLOAD("omp target teams distribute parallel for \
152  map(always, to : id_array[:num_accepted])")
153  for (int i = 0; i < num_accepted; i++)
154  {
155  const int iw = id_array[i];
156  RealType* RSoA_dev_ptr = mw_rosa_ptr[iw];
157  for (int id = 0; id < QMCTraits::DIM; id++)
158  RSoA_dev_ptr[iat + rsoa_stride * id] = mw_pos_ptr[iw + mw_pos_stride * id];
159  }
160  }
161 
162  const PosVectorSoa& getAllParticlePos() const override { return RSoA_hostview; }
163  PosType getOneParticlePos(size_t iat) const override { return RSoA_hostview[iat]; }
164 
165  void donePbyP() override
166  {
167  is_nw_new_pos_prepared = false;
169  {
170  updateH2D();
172  }
173  }
174 
175  const RealType* getDevicePtr() const { return RSoA.device_data(); }
176 
177  const auto& getFusedNewPosBuffer() const { return mw_mem_handle_.getResource().mw_new_pos; }
178 
179  void createResource(ResourceCollection& collection) const override
180  {
181  auto resource_index = collection.addResource(std::make_unique<MultiWalkerMem>());
182  }
183 
185  const RefVectorWithLeader<DynamicCoordinates>& coords_list) const override
186  {
188  collection.lendResource<MultiWalkerMem>();
189 
190  auto& mw_rsoa_ptrs(mw_mem.mw_rsoa_ptrs);
191  const auto nw = coords_list.size();
192  mw_rsoa_ptrs.resize(nw);
193  for (int iw = 0; iw < nw; iw++)
194  {
195  auto& coords = coords_list.getCastedElement<RealSpacePositionsOMPTarget>(iw);
196  mw_rsoa_ptrs[iw] = coords.RSoA.device_data();
197  }
198  mw_rsoa_ptrs.updateTo();
199  }
200 
202  const RefVectorWithLeader<DynamicCoordinates>& coords_list) const override
203  {
205  }
206 
207  const auto& getMultiWalkerRSoADevicePtrs() const { return mw_mem_handle_.getResource().mw_rsoa_ptrs; }
208 
209 private:
210  ///particle positions in SoA layout
212 
213  ///multi walker shared memory buffer
214  struct MultiWalkerMem : public Resource
215  {
216  ///one particle new/old positions in SoA layout
218 
219  /// accept list
221 
222  /// RSoA device ptr list
224 
225  MultiWalkerMem() : Resource("MultiWalkerMem") {}
226 
228 
229  std::unique_ptr<Resource> makeClone() const override { return std::make_unique<MultiWalkerMem>(*this); }
230  };
231 
233 
234  ///host view of RSoA
236 
237  ///if true, host position has been changed while the device copy has not been updated.
239 
240  ///if true, mw_new_pos has been updated with active positions.
242 
243  void updateH2D()
244  {
245  RealType* data = RSoA.data();
246  PRAGMA_OFFLOAD("omp target update to(data[0:RSoA.capacity()*QMCTraits::DIM])")
248  }
249 };
250 } // namespace qmcplusplus
251 #endif
DynamicCoordinateKind
enumerator for DynamicCoordinates kinds
size_t addResource(std::unique_ptr< Resource > &&res, bool noprint=false)
std::ostream & app_warning()
Definition: OutputManager.h:69
void takebackResource(ResourceHandle< RS > &res_handle)
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
VectorSoaContainer< RealType, QMCTraits::DIM, OMPallocator< RealType, PinnedAlignedAllocator< RealType > > > RSoA
particle positions in SoA layout
quantum variables of all the particles
ResourceHandle manages the temporary resource referenced from a collection.
void setAllParticlePos(const ParticlePos &R) override
overwrite the positions of all the particles.
Soa Container for D-dim vectors.
SoA adaptor class for Vector<TinyVector<T,D> >
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
bool is_host_position_changed_
if true, host position has been changed while the device copy has not been updated.
Attaches a unit to a Vector for IO.
std::unique_ptr< DynamicCoordinates > makeClone() override
size_type size() const
return the current size
Definition: OhmmsVector.h:162
Vector< RealType *, OMPallocator< RealType *, PinnedAlignedAllocator< RealType * > > > mw_rsoa_ptrs
RSoA device ptr list.
const PosVectorSoa & getAllParticlePos() const override
all particle position accessor
void setOneParticlePos(const PosType &pos, size_t iat) override
overwrite the position of one the particle.
Introduced to handle virtual moves and ratio computations, e.g.
CASTTYPE & getCastedElement(size_t i) const
bool is_nw_new_pos_prepared
if true, mw_new_pos has been updated with active positions.
void copyIn(const Vector< TinyVector< T, D >> &in)
AoS to SoA : copy from Vector<TinyVector<>>
Vector< int, OMPallocator< int, PinnedAlignedAllocator< int > > > mw_accept_indices
accept list
void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< DynamicCoordinates > &coords_list) const override
acquire a shared resource from a collection
void mw_acceptParticlePos(const RefVectorWithLeader< DynamicCoordinates > &coords_list, size_t iat, const std::vector< PosType > &new_positions, const std::vector< bool > &isAccepted) const override
overwrite the positions of particles with a uniform id in all the walkers upon acceptance.
void resize(size_t n) override
resize internal storages based on the number of particles
VectorSoaContainer< RealType, QMCTraits::DIM, OMPallocator< RealType, PinnedAlignedAllocator< RealType > > > mw_new_pos
one particle new/old positions in SoA layout
RealSpacePositionsOMPTarget(const RealSpacePositionsOMPTarget &in)
void donePbyP() override
secure internal data consistency after p-by-p moves
ResourceHandle< RS > lendResource()
void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< DynamicCoordinates > &coords_list) const override
return a shared resource to a collection
size_type size() const
return the physical size
void attachReference(size_type n, size_type n_padded, T *ptr)
attach to pre-allocated data
size_t size() const override
return the number of particles
PosType getOneParticlePos(size_t iat) const override
one particle position accessor
void mw_copyActivePos(const RefVectorWithLeader< DynamicCoordinates > &coords_list, size_t iat, const std::vector< PosType > &new_positions) const override
copy the active positions of particles with a uniform id in all the walkers to a single internal buff...