QMCPACK
CloneManager.cpp
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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
10 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
11 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
12 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
13 //
14 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
15 //////////////////////////////////////////////////////////////////////////////////////
16 
17 
18 #include "CloneManager.h"
19 #include "MemoryUsage.h"
21 #include "Message/Communicate.h"
22 #include "Concurrency/OpenMP.h"
24 #include "Utilities/qmc_common.h"
25 #if !defined(REMOVE_TRACEMANAGER)
27 #else
28 using TraceManager = int;
29 #endif
30 
31 //comment this out to use only method to clone
32 #define ENABLE_CLONE_PSI_AND_H
33 
34 namespace qmcplusplus
35 {
36 //initialization of the static wClones
37 UPtrVector<MCWalkerConfiguration> CloneManager::wClones_uptr;
38 std::vector<MCWalkerConfiguration*> CloneManager::wClones;
39 //initialization of the static psiClones
40 UPtrVector<TrialWaveFunction> CloneManager::psiClones_uptr;
41 std::vector<TrialWaveFunction*> CloneManager::psiClones;
42 //initialization of the static guideClones
43 UPtrVector<TrialWaveFunction> CloneManager::guideClones_uptr;
44 std::vector<TrialWaveFunction*> CloneManager::guideClones;
45 
46 UPtrVector<MCWalkerConfiguration> CloneManager::wgClones;
47 //initialization of the static hClones
48 UPtrVector<QMCHamiltonian> CloneManager::hClones_uptr;
49 std::vector<QMCHamiltonian*> CloneManager::hClones;
50 
51 std::vector<UPtrVector<MCWalkerConfiguration>> CloneManager::WPoolClones_uptr;
52 std::vector<std::vector<MCWalkerConfiguration*>> CloneManager::WPoolClones;
53 std::vector<UPtrVector<TrialWaveFunction>> CloneManager::PsiPoolClones_uptr;
54 std::vector<std::vector<TrialWaveFunction*>> CloneManager::PsiPoolClones;
55 std::vector<UPtrVector<QMCHamiltonian>> CloneManager::HPoolClones_uptr;
56 std::vector<std::vector<QMCHamiltonian*>> CloneManager::HPoolClones;
57 
59 {
60  HPoolClones.clear();
61  HPoolClones_uptr.clear();
62  PsiPoolClones.clear();
63  PsiPoolClones_uptr.clear();
64  WPoolClones.clear();
65  WPoolClones_uptr.clear();
66 
67  hClones.clear();
68  hClones_uptr.clear();
69  guideClones.clear();
70  guideClones_uptr.clear();
71  psiClones.clear();
72  psiClones_uptr.clear();
73  wClones.clear();
74  wClones_uptr.clear();
75 }
76 
77 /// Constructor.
79 
80 ///cleanup non-static data members
82 {
83  delete_iter(Movers.begin(), Movers.end());
85 
86 #if !defined(REMOVE_TRACEMANAGER)
87  delete_iter(traceClones.begin(), traceClones.end());
88 #endif
89 }
90 
92 {
93  if (wClones.size())
94  {
95  app_log() << " Cannot make clones again. Use existing " << NumThreads << " clones" << std::endl;
96  return;
97  }
98  wClones.resize(NumThreads);
99  psiClones.resize(NumThreads);
100  hClones.resize(NumThreads);
101  wClones[0] = &w;
102  psiClones[0] = &psi;
103  hClones[0] = &ham;
104  if (NumThreads == 1)
105  return;
106 
107  wClones_uptr.resize(NumThreads - 1);
108  psiClones_uptr.resize(NumThreads - 1);
109  hClones_uptr.resize(NumThreads - 1);
110 
111  app_log() << " CloneManager::makeClones makes " << NumThreads << " clones for W/Psi/H." << std::endl;
112  app_log() << " Cloning methods for both Psi and H are used" << std::endl;
113  print_mem("Memory Usage before cloning", app_log());
115  // clang-format off
116  #pragma omp parallel
117  {
118  // check sizes
119  #pragma omp master
121  throw std::runtime_error("CloneManager::makeClones Inconsist NumThreads and omp_get_num_threads()!\n");
122 
123  const int ip = omp_get_thread_num();
124  if (ip > 0)
125  {
126  // all the [ip] objects must be created on the ip threads to have first touch accurate.
127  wClones_uptr[ip - 1] = std::make_unique<MCWalkerConfiguration>(w);
128  wClones[ip] = wClones_uptr[ip - 1].get();
129  psiClones_uptr[ip - 1] = psi.makeClone(*wClones[ip]);
130  psiClones[ip] = psiClones_uptr[ip-1].get();
131  hClones_uptr[ip - 1] = ham.makeClone(*wClones[ip], *psiClones[ip]);
132  hClones[ip] = hClones_uptr[ip-1].get();
133  }
134  }
135  // clang-format on
136  infoLog.resume();
138  print_mem("Memory Usage after cloning", app_log());
139 }
140 
141 
143  std::vector<TrialWaveFunction*>& psipool,
144  std::vector<QMCHamiltonian*>& hampool)
145 {
146  if (WPoolClones.size())
147  {
148  app_log() << " Cannot make clones again. Use existing " << NumThreads << " clones" << std::endl;
149  return;
150  }
151  IndexType nPsi = psipool.size();
152 
153  wClones.resize(NumThreads);
154  PsiPoolClones.resize(NumThreads);
155  HPoolClones.resize(NumThreads);
156  wClones[0] = &w;
157  PsiPoolClones[0] = psipool;
158  HPoolClones[0] = hampool;
159 
160  if (NumThreads == 1)
161  return;
162 
163  wClones_uptr.resize(NumThreads - 1);
164  PsiPoolClones_uptr.resize(NumThreads - 1);
165  HPoolClones_uptr.resize(NumThreads - 1);
166 
167  app_log() << " CloneManager::makeClones makes " << NumThreads << " clones for W/Psi/H Pools." << std::endl;
168  app_log() << " Cloning methods for both Psi and H are used" << std::endl;
170 
171  bool io_node = qmc_common.io_node;
172  qmc_common.io_node = false;
173 
174  for (int ip = 1; ip < NumThreads; ++ip)
175  {
176  PsiPoolClones[ip].resize(nPsi);
177  PsiPoolClones_uptr[ip - 1].resize(nPsi);
178  HPoolClones[ip].resize(nPsi);
179  HPoolClones_uptr[ip - 1].resize(nPsi);
180 
181  wClones_uptr[ip - 1] = std::make_unique<MCWalkerConfiguration>(w);
182  wClones[ip] = wClones_uptr[ip - 1].get();
183  for (int ipsi = 0; ipsi < psipool.size(); ipsi++)
184  {
185  PsiPoolClones_uptr[ip - 1][ipsi] = psipool[ipsi]->makeClone(w);
186  PsiPoolClones[ip][ipsi] = PsiPoolClones_uptr[ip - 1][ipsi].get();
187  HPoolClones_uptr[ip - 1][ipsi] = hampool[ipsi]->makeClone(w, *psipool[ipsi]);
188  HPoolClones[ip][ipsi] = HPoolClones_uptr[ip - 1][ipsi].get();
189  }
190  }
192  infoLog.resume();
193  qmc_common.io_node = io_node;
194 }
195 
196 
198 {
199  if (guideClones.size())
200  {
201  app_log() << " Cannot make clones again. Use existing " << NumThreads << " clones" << std::endl;
202  return;
203  }
204  guideClones.resize(NumThreads);
205  guideClones[0] = &guide;
206  if (NumThreads == 1)
207  return;
208  guideClones_uptr.resize(NumThreads - 1);
209  app_log() << " CloneManager::makeClones makes " << NumThreads << " clones for guide/wg." << std::endl;
211  for (int ip = 1; ip < NumThreads; ++ip)
212  {
213  guideClones_uptr[ip - 1] = guide.makeClone(*wClones[ip]);
214  guideClones[ip] = guideClones_uptr[ip - 1].get();
215  }
217  infoLog.resume();
218 }
219 
220 
222 {
223  if (guideClones.size())
224  {
225  app_log() << " Cannot make clones again. Use existing " << NumThreads << " clones" << std::endl;
226  return;
227  }
228  guideClones.resize(NumThreads);
229  wgClones.resize(NumThreads);
230  guideClones[0] = &guide;
231  wgClones[0] = std::make_unique<MCWalkerConfiguration>(wg);
232  if (NumThreads == 1)
233  return;
234  guideClones_uptr.resize(NumThreads - 1);
235  app_log() << " CloneManager::makeClones makes " << NumThreads << " clones for guide/wg." << std::endl;
237  for (int ip = 1; ip < NumThreads; ++ip)
238  {
239  wgClones[ip] = std::make_unique<MCWalkerConfiguration>(wg);
240  guideClones_uptr[ip - 1] = guide.makeClone(*wgClones[ip]);
241  guideClones[ip] = guideClones_uptr[ip - 1].get();
242  }
244  infoLog.resume();
245 }
246 
248 {
249  IndexType nAcceptTot = 0;
250  IndexType nRejectTot = 0;
251  for (int ip = 0; ip < NumThreads; ip++)
252  {
253  nAcceptTot += Movers[ip]->nAccept;
254  nRejectTot += Movers[ip]->nReject;
255  }
256 #if defined(__GNUC__) || !defined(NDEBUG)
257  // Attempt to detect compiler vectorization errors by computing
258  // acceptance ratio in a different way to the above loop
259  IndexType nAcceptTot_debug = 0;
260  IndexType nRejectTot_debug = 0;
261  std::vector<int> vec(NumThreads);
262  for (int ip = 0; ip < NumThreads; ip++)
263  {
264  vec[ip] = Movers[ip]->nAccept;
265  nAcceptTot_debug += vec[ip];
266  vec[ip] = Movers[ip]->nReject;
267  nRejectTot_debug += vec[ip];
268  }
269  if (nAcceptTot != nAcceptTot_debug || nRejectTot != nRejectTot_debug)
270  {
271  app_warning() << " Potential compiler bug detected!"
272  << " Overwriting nAcceptTot wrong value " << nAcceptTot << " with correct value " << nAcceptTot_debug
273  << "."
274  << " Overwriting nRejectTot wrong value " << nRejectTot << " with correct value " << nRejectTot_debug
275  << "." << std::endl;
276  nAcceptTot = nAcceptTot_debug;
277  nRejectTot = nRejectTot_debug;
278  }
279 #endif
280  return static_cast<RealType>(nAcceptTot) / static_cast<RealType>(nAcceptTot + nRejectTot);
281 }
282 
284 {
286  for(int i = 0; i < wlog_collectors.size(); i++)
287  refs.push_back(*wlog_collectors[i]);
288  return refs;
289 }
290 
291 } // namespace qmcplusplus
UPtrVector< WalkerLogCollector > wlog_collectors
trace collectors
Definition: CloneManager.h:79
void pause()
Pause the summary and log streams.
A set of walkers that are to be advanced by Metropolis Monte Carlo.
std::ostream & app_warning()
Definition: OutputManager.h:69
static std::vector< TrialWaveFunction * > psiClones
Definition: CloneManager.h:65
virtual ~CloneManager()
virtual destructor
void delete_iter(IT first, IT last)
delete the pointers in [first,last)
std::vector< int > wPerRank
Walkers per MPI rank.
Definition: CloneManager.h:91
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::RealType RealType
Definition: Configuration.h:58
static UPtrVector< MCWalkerConfiguration > wgClones
Definition: CloneManager.h:62
static std::vector< std::vector< TrialWaveFunction * > > PsiPoolClones
Definition: CloneManager.h:85
static std::vector< TrialWaveFunction * > guideClones
Definition: CloneManager.h:68
InfoStream infoSummary
static std::vector< MCWalkerConfiguration * > wClones
Definition: CloneManager.h:61
std::ostream & app_log()
Definition: OutputManager.h:65
Collection of Local Energy Operators.
std::vector< QMCUpdateBase * > Movers
update engines
Definition: CloneManager.h:73
void print_mem(const std::string &title, std::ostream &log)
Definition: MemoryUsage.cpp:30
void resume()
Continue output on the stream used before pausing.
Definition: InfoStream.cpp:47
std::unique_ptr< TrialWaveFunction > makeClone(ParticleSet &tqp) const
InfoStream infoLog
static UPtrVector< TrialWaveFunction > guideClones_uptr
guide wavefunctions
Definition: CloneManager.h:67
OutputManagerClass outputManager(Verbosity::HIGH)
static UPtrVector< TrialWaveFunction > psiClones_uptr
trial wavefunctions
Definition: CloneManager.h:64
QMCTraits::IndexType IndexType
Definition: FSUtilities.h:11
static std::vector< UPtrVector< MCWalkerConfiguration > > WPoolClones_uptr
Definition: CloneManager.h:82
omp_int_t omp_get_thread_num()
Definition: OpenMP.h:25
static UPtrVector< MCWalkerConfiguration > wClones_uptr
walkers
Definition: CloneManager.h:60
omp_int_t omp_get_max_threads()
Definition: OpenMP.h:26
std::vector< EstimatorManagerBase * > estimatorClones
estimator managers
Definition: CloneManager.h:75
bool io_node
true, print out file
Definition: qmc_common.h:39
const IndexType NumThreads
number of threads
Definition: CloneManager.h:54
void makeClones(MCWalkerConfiguration &w, TrialWaveFunction &psi, QMCHamiltonian &ham)
omp_int_t omp_get_num_threads()
Definition: OpenMP.h:27
CloneManager()
Constructor.
static std::vector< QMCHamiltonian * > hClones
Definition: CloneManager.h:71
std::vector< std::reference_wrapper< T > > RefVector
Declaration of HamiltonianPool.
static std::vector< UPtrVector< TrialWaveFunction > > PsiPoolClones_uptr
Definition: CloneManager.h:84
static UPtrVector< QMCHamiltonian > hClones_uptr
Hamiltonians.
Definition: CloneManager.h:70
Class to represent a many-body trial wave function.
Manager class to handle multiple threads.
RealType acceptRatio() const
static std::vector< std::vector< QMCHamiltonian * > > HPoolClones
Definition: CloneManager.h:87
std::vector< TraceManager * > traceClones
trace managers
Definition: CloneManager.h:77
RefVector< WalkerLogCollector > getWalkerLogCollectorRefs()
QMCState qmc_common
a unique QMCState during a run
Definition: qmc_common.cpp:111
std::unique_ptr< QMCHamiltonian > makeClone(ParticleSet &qp, TrialWaveFunction &psi) const
return a clone
static std::vector< std::vector< MCWalkerConfiguration * > > WPoolClones
Definition: CloneManager.h:83
static std::vector< UPtrVector< QMCHamiltonian > > HPoolClones_uptr
Definition: CloneManager.h:86