Panzer Version of the Day
Loading...
Searching...
No Matches
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
60namespace 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 //
121 MemUsage getMemoryUsage(const Teuchos::Comm<int>& comm)
122 {
123 MemUsage current = getCurrentRSS(comm);
124 MemUsage peak = getPeakRSS(comm);
125 return current + peak;
126 } // end of getMemoryUsage()
127
129 //
130 // getPeakRSS()
131 //
133 MemUsage getPeakRSS(const Teuchos::Comm<int>& comm)
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 //
190 MemUsage getCurrentRSS(const Teuchos::Comm<int>& comm)
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 {
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
PHX::MDField< ScalarT, panzer::Cell, panzer::IP > result
A field that will be used to build up the result of the integral we're performing.
MemUsage getCurrentRSS(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.
MemUsage getMemoryUsage(const Teuchos::Comm< int > &comm)
Get memory usage in B.
MemUsage getPeakRSS(const Teuchos::Comm< int > &comm)
The memory usage information.