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 // Panzer: A partial differential equation assembly
4 // engine for strongly coupled complex multiphysics systems
5 //
6 // Copyright 2011 NTESS and the Panzer contributors.
7 // SPDX-License-Identifier: BSD-3-Clause
8 // *****************************************************************************
9 // @HEADER
10 
12 //
13 // Much of what appears below was taken from getRSS.c from
14 // Author: David Robert Nadeau
15 // Site: http://NadeauSoftware.com/
16 // License: Creative Commons Attribution 3.0 Unported License
17 // http://creativecommons.org/licenses/by/3.0/deed.en_US
18 // and was extended to gather memory usage information from all processors in
19 // Teuchos::Comm<int>& comm.
20 //
21 // Note: On Windows, link with psapi.lib.
22 //
24 
25 #include <Panzer_MemUtils.hpp>
26 #include <Teuchos_CommHelpers.hpp>
27 
28 #if defined(_WIN32)
29 # include <windows.h>
30 # include <psapi.h>
31 #elif defined(__unix__) || \
32  defined(__unix) || \
33  defined(unix) || \
34  (defined(__APPLE__) && \
35  defined(__MACH__))
36 # include <unistd.h>
37 # include <sys/resource.h>
38 # if defined(__APPLE__) && \
39  defined(__MACH__)
40 # include <mach/mach.h>
41 # elif (defined(_AIX) || \
42  defined(__TOS__AIX__)) || \
43  (defined(__sun__) || \
44  defined(__sun) || \
45  defined(sun) && \
46  (defined(__SVR4) || \
47  defined(__svr4__)))
48 # include <fcntl.h>
49 # include <procfs.h>
50 # elif defined(__linux__) || \
51  defined(__linux) || \
52  defined(linux) || \
53  defined(__gnu_linux__)
54 # include <stdio.h>
55 # endif // defined(__APPLE__) && ...
56 #else
57 # error "Cannot define getPeakRSS( ) or getCurrentRSS( ) for an unknown OS."
58 #endif // defined(_WIN32)
59 
60 namespace panzer
61 {
63  //
64  // printMemoryUsage()
65  //
67  void printMemoryUsage(std::ostream& s, const Teuchos::Comm<int>& comm)
68  {
69  MemUsage mem = getMemoryUsage(comm);
70  printMemoryUsage(s, comm, mem);
71  return;
72  } // end of printMemoryUsage()
73 
75  //
76  // printMemoryUsage()
77  //
79  void printMemoryUsage(std::ostream& s, const Teuchos::Comm<int>& comm,
80  const MemUsage& mem)
81  {
82  using std::endl;
83  if (0 == comm.getRank())
84  {
85  s << "Estimated memory usage across all processors:" << endl
86  << " Current Peak " << endl
87  << " ------------ ------------" << endl << " Min: ";
88  pretty(s, mem.currMin); pretty(s, mem.peakMin); s << endl << " Max: ";
89  pretty(s, mem.currMax); pretty(s, mem.peakMax); s << endl << " Tot: ";
90  pretty(s, mem.currTot); pretty(s, mem.peakTot); s << endl;
91  }
92  return;
93  } // end of printMemoryUsage()
94 
96  //
97  // pretty()
98  //
100  void pretty(std::ostream& s, size_t num)
101  {
102  s << std::fixed;
103  s.precision(3);
104  s << std::setw(9) << std::setfill(' ');
105  if (num < (1 << 10))
106  s << num << " B ";
107  else if (num < (1 << 20))
108  s << (static_cast<double>(num) / (1 << 10)) << " KB ";
109  else if (num < (1 << 30))
110  s << (static_cast<double>(num) / (1 << 20)) << " MB ";
111  else
112  s << (static_cast<double>(num) / (1 << 30)) << " GB ";
113  return;
114  } // end of pretty()
115 
117  //
118  // getMemoryUsage()
119  //
122  {
123  MemUsage current = getCurrentRSS(comm);
124  MemUsage peak = getPeakRSS(comm);
125  return current + peak;
126  } // end of getMemoryUsage()
127 
129  //
130  // getPeakRSS()
131  //
134  {
135  size_t mem(0);
136 
137  // Windows
138 # if defined(_WIN32)
139  PROCESS_MEMORY_COUNTERS info;
140  GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
141  mem = (size_t)(info.PeakWorkingSetSize);
142 
143  // AIX and Solaris
144 # elif (defined(_AIX) || \
145  defined(__TOS__AIX__)) || \
146  (defined(__sun__) || \
147  defined(__sun) || \
148  defined(sun) && \
149  (defined(__SVR4) || \
150  defined(__svr4__)))
151  struct psinfo psinfo;
152  int fd = -1;
153  if ((fd = open("/proc/self/psinfo", O_RDONLY)) == -1)
154  mem = (size_t)(0L); // Can't open?
155  if (read(fd, &psinfo, sizeof(psinfo)) != sizeof(psinfo))
156  {
157  close(fd);
158  mem = (size_t)(0L); // Can't read?
159  }
160  close(fd);
161  mem = (size_t)(psinfo.pr_rssize * 1024L);
162 
163  // BSD, Linux, and OSX
164 # elif defined(__unix__) || \
165  defined(__unix) || \
166  defined(unix) || \
167  (defined(__APPLE__) && \
168  defined(__MACH__))
169  struct rusage rusage;
170  getrusage(RUSAGE_SELF, &rusage);
171 # if defined(__APPLE__) && \
172  defined(__MACH__)
173  mem = (size_t)(rusage.ru_maxrss);
174 # else
175  mem = (size_t)(rusage.ru_maxrss * 1024L);
176 # endif // defined(__APPLE__) && ...
177 
178  // Unknown OS
179 # else
180  mem = (size_t)(0L); // Unsupported.
181 # endif // defined(_WIN32)
182  return reduceMemUsage(mem, comm, MEM_USAGE_PEAK);
183  } // end of getPeakRSS()
184 
186  //
187  // getCurrentRSS()
188  //
191  {
192  size_t mem(0);
193 
194  // Windows
195 # if defined(_WIN32)
196  PROCESS_MEMORY_COUNTERS info;
197  GetProcessMemoryInfo(GetCurrentProcess(), &info, sizeof(info));
198  mem = (size_t)(info.WorkingSetSize);
199 
200  // OSX
201 # elif defined(__APPLE__) && \
202  defined(__MACH__)
203  struct mach_task_basic_info info;
204  mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
205  if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO,
206  (task_info_t)(&info), &infoCount) != KERN_SUCCESS)
207  mem = (size_t)(0L); // Can't access?
208  mem = (size_t)(info.resident_size);
209 
210  // Linux
211 # elif defined(__linux__) || \
212  defined(__linux) || \
213  defined(linux) || \
214  defined(__gnu_linux__)
215  long rss = 0L;
216  FILE* fp = NULL;
217  if ((fp = fopen("/proc/self/statm", "r")) == NULL)
218  mem = (size_t)(0L); // Can't open?
219  if (fscanf(fp, "%*s%ld", &rss) != 1)
220  {
221  fclose(fp);
222  mem = (size_t)(0L); // Can't read?
223  }
224  fclose(fp);
225  mem = (size_t)(rss) * (size_t)(sysconf(_SC_PAGESIZE));
226 
227  // AIX, BSD, Solaris, and Unknown OS
228 # else
229  mem = (size_t)(0L); // Unsupported.
230 # endif // defined(_WIN32)
231  return reduceMemUsage(mem, comm, MEM_USAGE_CURRENT);
232  } // end of getCurrentRSS()
233 
235  //
236  // reduceMemUsage()
237  //
239  MemUsage reduceMemUsage(size_t& mem, const Teuchos::Comm<int>& comm,
240  const MemUsageType& type)
241  {
242  size_t min(0), max(0), tot(0);
243  Teuchos::reduceAll(comm, Teuchos::REDUCE_MIN, 1, &mem, &min);
244  Teuchos::reduceAll(comm, Teuchos::REDUCE_MAX, 1, &mem, &max);
245  Teuchos::reduceAll(comm, Teuchos::REDUCE_SUM, 1, &mem, &tot);
247  switch (type)
248  {
249  case MEM_USAGE_CURRENT:
250  result.currMin = min;
251  result.currMax = max;
252  result.currTot = tot;
253  break;
254  case MEM_USAGE_PEAK:
255  result.peakMin = min;
256  result.peakMax = max;
257  result.peakTot = tot;
258  break;
259  }
260  return result;
261  } // end of reduceMemUsage()
262 } // 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.