OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
MemoryProfiler.cpp
Go to the documentation of this file.
1//
2// Class MemoryProfiler
3// This class writes a SDDS file with virtual memory usage information (Linux only).
4//
5// Copyright (c) 2019, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// Implemented as part of the PhD thesis
9// "Precise Simulations of Multibunches in High Intensity Cyclotrons"
10//
11// This file is part of OPAL.
12//
13// OPAL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation, either version 3 of the License, or
16// (at your option) any later version.
17//
18// You should have received a copy of the GNU General Public License
19// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20//
22
25#include "Physics/Units.h"
26#include "Utilities/Timer.h"
28
29#include "Ippl.h"
30
31#ifdef __linux__
32#include <sys/types.h>
33#include <unistd.h>
34#endif
35#include <sstream>
36
37MemoryProfiler::MemoryProfiler(const std::string& fname, bool restart)
38 : SDDSWriter(fname, restart)
39{
40 procinfo_m = {
41 {"VmPeak:", VirtualMemory::VMPEAK},
42 {"VmSize:", VirtualMemory::VMSIZE},
43 {"VmHWM:", VirtualMemory::VMHWM},
44 {"VmRSS:", VirtualMemory::VMRSS},
45 {"VmStk:", VirtualMemory::VMSTK},
46 {"VmData:", VirtualMemory::VMDATA},
47 {"VmExe:", VirtualMemory::VMEXE},
48 {"VmLck:", VirtualMemory::VMLCK},
49 {"VmPin:", VirtualMemory::VMPIN},
50 {"VmLib:", VirtualMemory::VMLIB},
51 {"VmPTE:", VirtualMemory::VMPTE},
52 {"VmPMD:", VirtualMemory::VMPMD},
53 {"VmSwap:", VirtualMemory::VMSWAP}
54 };
55
56 vmem_m.resize(procinfo_m.size());
57 unit_m.resize(procinfo_m.size());
58}
59
60
62
63 if (this->hasColumns()) {
64 return;
65 }
66
67 columns_m.addColumn("t", "double", "ns", "Time");
68
69 columns_m.addColumn("s", "double", "m", "Path length");
70
71 // peak virtual memory size
72 columns_m.addColumn("VmPeak-Min", "double", unit_m[VirtualMemory::VMPEAK],
73 "Minimum peak virtual memory size");
74
75 columns_m.addColumn("VmPeak-Max", "double", unit_m[VirtualMemory::VMPEAK],
76 "Maximum peak virtual memory size");
77
78 columns_m.addColumn("VmPeak-Avg", "double", unit_m[VirtualMemory::VMPEAK],
79 "Average peak virtual memory size");
80
81 // virtual memory size
82 columns_m.addColumn("VmSize-Min", "double", unit_m[VirtualMemory::VMSIZE],
83 "Minimum virtual memory size");
84
85 columns_m.addColumn("VmSize-Max", "double", unit_m[VirtualMemory::VMSIZE],
86 "Maximum virtual memory size");
87
88 columns_m.addColumn("VmSize-Avg", "double", unit_m[VirtualMemory::VMSIZE],
89 "Average virtual memory size");
90
91 // peak resident set size ("high water mark")
92 columns_m.addColumn("VmHWM-Min", "double", unit_m[VirtualMemory::VMHWM],
93 "Minimum peak resident set size");
94
95 columns_m.addColumn("VmHWM-Max", "double", unit_m[VirtualMemory::VMHWM],
96 "Maximum peak resident set size");
97
98 columns_m.addColumn("VmHWM-Avg", "double", unit_m[VirtualMemory::VMHWM],
99 "Average peak resident set size");
100
101 // resident set size
102 columns_m.addColumn("VmRSS-Min", "double", unit_m[VirtualMemory::VMRSS],
103 "Minimum resident set size");
104
105 columns_m.addColumn("VmRSS-Max", "double", unit_m[VirtualMemory::VMRSS],
106 "Maximum resident set size");
107
108 columns_m.addColumn("VmRSS-Avg", "double", unit_m[VirtualMemory::VMRSS],
109 "Average resident set size");
110
111 // stack size
112 columns_m.addColumn("VmStk-Min", "double", unit_m[VirtualMemory::VMSTK],
113 "Minimum stack size");
114
115 columns_m.addColumn("VmStk-Max", "double", unit_m[VirtualMemory::VMSTK],
116 "Maximum stack size");
117
118 columns_m.addColumn("VmStk-Avg", "double", unit_m[VirtualMemory::VMSTK],
119 "Average stack size");
120
121 if ( mode_m == std::ios::app )
122 return;
123
124 OPALTimer::Timer simtimer;
125
126 std::string dateStr(simtimer.date());
127 std::string timeStr(simtimer.time());
128
129 std::stringstream ss;
130 ss << "Memory statistics '"
131 << OpalData::getInstance()->getInputFn() << "' "
132 << dateStr << "" << timeStr;
133
134 this->addDescription(ss.str(), "memory info");
135
136 this->addDefaultParameters();
137
138 this->addInfo("ascii", 1);
139}
140
141
143#ifdef __linux__
144 static pid_t pid = getpid();
145 std::string fname = "/proc/" + std::to_string(pid) + "/status";
146
147 if ( !std::filesystem::exists(fname) ) {
148 throw OpalException("MemoryProfiler::update()",
149 "File '" + fname + "' doesn't exist.");
150 }
151
152 std::ifstream ifs(fname.c_str());
153
154 if ( !ifs.is_open() ) {
155 throw OpalException("MemoryProfiler::update()",
156 "Failed to open '" + fname + "'.");
157 }
158
159 std::string token;
160 while (ifs >> token) {
161 if ( !procinfo_m.count(token) ) {
162 continue;
163 }
164 int idx = procinfo_m[token];
165 ifs >> vmem_m[idx]
166 >> unit_m[idx];
167 }
168
169 ifs.close();
170#endif
171}
172
173
175 vm_t& vmMax,
176 vm_t& vmAvg)
177{
178 if ( Ippl::getNodes() == 1 ) {
179 for (unsigned int i = 0; i < vmem_m.size(); ++i) {
180 vmMin[i] = vmMax[i] = vmAvg[i] = vmem_m[i];
181 }
182 return;
183 }
184
185 new_reduce(vmem_m.data(), vmAvg.data(), vmem_m.size(), std::plus<double>());
186
187 double inodes = 1.0 / double(Ippl::getNodes());
188 for (auto& vm : vmAvg) {
189 vm *= inodes;
190 }
191
192 new_reduce(vmem_m.data(), vmMin.data(), vmem_m.size(), std::less<double>());
193 new_reduce(vmem_m.data(), vmMax.data(), vmem_m.size(), std::greater<double>());
194}
195
196
198
199 this->update();
200
201 vm_t vmMin(vmem_m.size());
202 vm_t vmMax(vmem_m.size());
203 vm_t vmAvg(vmem_m.size());
204
205 this->compute(vmMin, vmMax, vmAvg);
206
207 if ( Ippl::myNode() != 0 ) {
208 return;
209 }
210
211 double pathLength = beam->get_sPos();
212
213 header();
214
215 this->open();
216
217 this->writeHeader();
218
219 columns_m.addColumnValue("t", beam->getT() * Units::s2ns); // 1
220 columns_m.addColumnValue("s", pathLength); // 2
221
222 // boost::variant can't overload double and long double. By using a
223 // string this shortcoming can be bypassed.
224 columns_m.addColumnValue("VmPeak-Min", toString(vmMin[VMPEAK]));
225 columns_m.addColumnValue("VmPeak-Max", toString(vmMax[VMPEAK]));
226 columns_m.addColumnValue("VmPeak-Avg", toString(vmAvg[VMPEAK]));
227
228 columns_m.addColumnValue("VmSize-Min", toString(vmMin[VMSIZE]));
229 columns_m.addColumnValue("VmSize-Max", toString(vmMax[VMSIZE]));
230 columns_m.addColumnValue("VmSize-Avg", toString(vmAvg[VMSIZE]));
231
232 columns_m.addColumnValue("VmHWM-Min", toString(vmMin[VMHWM]));
233 columns_m.addColumnValue("VmHWM-Max", toString(vmMax[VMHWM]));
234 columns_m.addColumnValue("VmHWM-Avg", toString(vmAvg[VMHWM]));
235
236 columns_m.addColumnValue("VmRSS-Min", toString(vmMin[VMRSS]));
237 columns_m.addColumnValue("VmRSS-Max", toString(vmMax[VMRSS]));
238 columns_m.addColumnValue("VmRSS-Avg", toString(vmAvg[VMRSS]));
239
240 columns_m.addColumnValue("VmStk-Min", toString(vmMin[VMSTK]));
241 columns_m.addColumnValue("VmStk-Max", toString(vmMax[VMSTK]));
242 columns_m.addColumnValue("VmStk-Avg", toString(vmAvg[VMSTK]));
243
244 this->writeRow();
245
246 this->close();
247}
void new_reduce(const T *input, T *output, int count, Op op, int root=0)
constexpr double s2ns
Definition Units.h:44
double get_sPos() const
double getT() const
std::string getInputFn()
get opals input filename
Definition OpalData.cpp:670
static OpalData * getInstance()
Definition OpalData.cpp:196
void compute(vm_t &vmMin, vm_t &vmMax, vm_t &vmAvg)
std::vector< long double > vm_t
void write(PartBunchBase< double, 3 > *beam) override
MemoryProfiler(const std::string &fname, bool restart)
std::map< std::string, int > procinfo_m
SDDSWriter(const std::string &fname, bool restart)
std::string toString(const T &val)
Definition SDDSWriter.h:191
SDDSColumnSet columns_m
Definition SDDSWriter.h:122
bool hasColumns() const
Definition SDDSWriter.h:200
void addDefaultParameters()
void addDescription(const std::string &text, const std::string &content)
Definition SDDSWriter.h:159
void writeHeader()
Write SDDS header.
std::ios_base::openmode mode_m
First write to the statistics output file.
Definition SDDSWriter.h:120
void writeRow()
Definition SDDSWriter.h:185
void addInfo(const std::string &mode, const size_t &no_row_counts)
Definition SDDSWriter.h:178
The base class for all OPAL exceptions.
std::string date() const
Return date.
std::string time() const
Return time.
static int getNodes()
Definition IpplInfo.cpp:670
static int myNode()
Definition IpplInfo.cpp:691