Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_MemUtils.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
44 //
45 // Much of what appears below was taken from getRSS.c from
46 // Author: David Robert Nadeau
47 // Site: http://NadeauSoftware.com/
48 // License: Creative Commons Attribution 3.0 Unported License
49 // http://creativecommons.org/licenses/by/3.0/deed.en_US
50 // and was extended to gather memory usage information from all processors in
51 // Teuchos::Comm<int>& comm.
52 //
53 // Note: On Windows, link with psapi.lib.
54 //
56 
57 #include <Panzer_MemUtils.hpp>
58 #include <Teuchos_CommHelpers.hpp>
59 
60 #if defined(_WIN32)
61 # include <windows.h>
62 # include <psapi.h>
63 #elif defined(__unix__) || \
64  defined(__unix) || \
65  defined(unix) || \
66  (defined(__APPLE__) && \
67  defined(__MACH__))
68 # include <unistd.h>
69 # include <sys/resource.h>
70 # if defined(__APPLE__) && \
71  defined(__MACH__)
72 # include <mach/mach.h>
73 # elif (defined(_AIX) || \
74  defined(__TOS__AIX__)) || \
75  (defined(__sun__) || \
76  defined(__sun) || \
77  defined(sun) && \
78  (defined(__SVR4) || \
79  defined(__svr4__)))
80 # include <fcntl.h>
81 # include <procfs.h>
82 # elif defined(__linux__) || \
83  defined(__linux) || \
84  defined(linux) || \
85  defined(__gnu_linux__)
86 # include <stdio.h>
87 # endif // defined(__APPLE__) && ...
88 #else
89 # error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
90 #endif // defined(_WIN32)
91 
92 namespace panzer
93 {
95  //
96  // printMemoryUsage()
97  //
99  void printMemoryUsage(std::ostream& s, const Teuchos::Comm<int>& comm)
100  {
101  MemUsage mem = getMemoryUsage(comm);
102  printMemoryUsage(s, comm, mem);
103  return;
104  } // end of printMemoryUsage()
105 
107  //
108  // printMemoryUsage()
109  //
111  void printMemoryUsage(std::ostream& s, const Teuchos::Comm<int>& comm,
112  const MemUsage& mem)
113  {
114  using std::endl;
115  if (0 == comm.getRank())
116  {
117  s << "Estimated memory usage across all processors:" << endl
118  << " Current Peak " << endl
119  << " ------------ ------------" << endl << " Min: ";
120  pretty(s, mem.currMin); pretty(s, mem.peakMin); s << endl << " Max: ";
121  pretty(s, mem.currMax); pretty(s, mem.peakMax); s << endl << " Tot: ";
122  pretty(s, mem.currTot); pretty(s, mem.peakTot); s << endl;
123  }
124  return;
125  } // end of printMemoryUsage()
126 
128  //
129  // pretty()
130  //
132  void pretty(std::ostream& s, size_t num)
133  {
134  s << std::fixed;
135  s.precision(3);
136  s << std::setw(9) << std::setfill(' ');
137  if (num < (1 << 10))
138  s << num << " B ";
139  else if (num < (1 << 20))
140  s << (static_cast<double>(num) / (1 << 10)) << " KB ";
141  else if (num < (1 << 30))
142  s << (static_cast<double>(num) / (1 << 20)) << " MB ";
143  else
144  s << (static_cast<double>(num) / (1 << 30)) << " GB ";
145  return;
146  } // end of pretty()
147 
149  //
150  // getMemoryUsage()
151  //
154  {
155  MemUsage current = getCurrentRSS(comm);
156  MemUsage peak = getPeakRSS(comm);
157  return current + peak;
158  } // end of getMemoryUsage()
159 
161  //
162  // getPeakRSS()
163  //
166  {
167  size_t mem(0);
168 
169  // Windows
170 # if defined(_WIN32)
171  PROCESS_MEMORY_COUNTERS info;
172  GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
173  mem = (size_t)(info.PeakWorkingSetSize);
174 
175  // AIX and Solaris
176 # elif (defined(_AIX) || \
177  defined(__TOS__AIX__)) || \
178  (defined(__sun__) || \
179  defined(__sun) || \
180  defined(sun) && \
181  (defined(__SVR4) || \
182  defined(__svr4__)))
183  struct psinfo psinfo;
184  int fd = -1;
185  if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
186  mem = (size_t)(0L); // Can't open?
187  if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo))
188  {
189  close(fd);
190  mem = (size_t)(0L); // Can't read?
191  }
192  close(fd);
193  mem = (size_t)(psinfo.pr_rssize * 1024L);
194 
195  // BSD, Linux, and OSX
196 # elif defined(__unix__) || \
197  defined(__unix) || \
198  defined(unix) || \
199  (defined(__APPLE__) && \
200  defined(__MACH__))
201  struct rusage rusage;
202  getrusage(RUSAGE_SELF, &rusage);
203 # if defined(__APPLE__) && \
204  defined(__MACH__)
205  mem = (size_t)(rusage.ru_maxrss);
206 # else
207  mem = (size_t)(rusage.ru_maxrss * 1024L);
208 # endif // defined(__APPLE__) && ...
209 
210  // Unknown OS
211 # else
212  mem = (size_t)(0L); // Unsupported.
213 # endif // defined(_WIN32)
214  return reduceMemUsage(mem, comm, MEM_USAGE_PEAK);
215  } // end of getPeakRSS()
216 
218  //
219  // getCurrentRSS()
220  //
223  {
224  size_t mem(0);
225 
226  // Windows
227 # if defined(_WIN32)
228  PROCESS_MEMORY_COUNTERS info;
229  GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
230  mem = (size_t)(info.WorkingSetSize);
231 
232  // OSX
233 # elif defined(__APPLE__) && \
234  defined(__MACH__)
235  struct mach_task_basic_info info;
236  mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
237  if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
238  (task_info_t)(&info), &infoCount) != KERN_SUCCESS)
239  mem = (size_t)(0L); // Can't access?
240  mem = (size_t)(info.resident_size);
241 
242  // Linux
243 # elif defined(__linux__) || \
244  defined(__linux) || \
245  defined(linux) || \
246  defined(__gnu_linux__)
247  long rss = 0L;
248  FILE* fp = NULL;
249  if ((fp = fopen("/proc/self/statm", "r")) == NULL)
250  mem = (size_t)(0L); // Can't open?
251  if (fscanf(fp, "%*s%ld", &rss) != 1)
252  {
253  fclose(fp);
254  mem = (size_t)(0L); // Can't read?
255  }
256  fclose(fp);
257  mem = (size_t)(rss) * (size_t)(sysconf(_SC_PAGESIZE));
258 
259  // AIX, BSD, Solaris, and Unknown OS
260 # else
261  mem = (size_t)(0L); // Unsupported.
262 # endif // defined(_WIN32)
263  return reduceMemUsage(mem, comm, MEM_USAGE_CURRENT);
264  } // end of getCurrentRSS()
265 
267  //
268  // reduceMemUsage()
269  //
271  MemUsage reduceMemUsage(size_t& mem, const Teuchos::Comm<int>& comm,
272  const MemUsageType& type)
273  {
274  size_t min(0), max(0), tot(0);
275  Teuchos::reduceAll(comm, Teuchos::REDUCE_MIN, 1, &mem, &min);
276  Teuchos::reduceAll(comm, Teuchos::REDUCE_MAX, 1, &mem, &max);
277  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, 1, &mem, &tot);
279  switch (type)
280  {
281  case MEM_USAGE_CURRENT:
282  result.currMin = min;
283  result.currMax = max;
284  result.currTot = tot;
285  break;
286  case MEM_USAGE_PEAK:
287  result.peakMin = min;
288  result.peakMax = max;
289  result.peakTot = tot;
290  break;
291  }
292  return result;
293  } // end of reduceMemUsage()
294 } // end namespace panzer
virtual int getRank() const =0
The memory usage information.
MemUsage getCurrentRSS(const Teuchos::Comm< int > &comm)
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we&#39;re performing.
MemUsage getMemoryUsage(const Teuchos::Comm< int > &comm)
Get memory usage in B.
MemUsage getPeakRSS(const Teuchos::Comm< int > &comm)
void pretty(std::ostream &s, size_t num)
void printMemoryUsage(std::ostream &s, const Teuchos::Comm< int > &comm)
Print memory usage to stream.
MemUsage reduceMemUsage(size_t &mem, const Teuchos::Comm< int > &comm, const MemUsageType &type)
Reduce the memory usage over all the processors.