Panzer Version of the Day
Loading...
Searching...
No Matches
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
92namespace 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 //
153 MemUsage getMemoryUsage(const Teuchos::Comm<int>& comm)
154 {
155 MemUsage current = getCurrentRSS(comm);
156 MemUsage peak = getPeakRSS(comm);
157 return current + peak;
158 } // end of getMemoryUsage()
159
161 //
162 // getPeakRSS()
163 //
165 MemUsage getPeakRSS(const Teuchos::Comm<int>& comm)
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 //
222 MemUsage getCurrentRSS(const Teuchos::Comm<int>& comm)
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 {
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
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.