OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
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//
21#include "MemoryProfiler.h"
22
23#ifdef __linux__
24#include <sys/types.h>
25#include <unistd.h>
26#endif
27
29#include "PartBunch/PartBunch.h"
30#include "Physics/Units.h"
32#include "Utilities/Timer.h"
33
34#include <filesystem>
35
36#include "Ippl.h"
37
38#include <sstream>
39
40MemoryProfiler::MemoryProfiler(const std::string& fname, bool restart)
41 : SDDSWriter(fname, restart) {
42 procinfo_m = {{"VmPeak:", VirtualMemory::VMPEAK}, {"VmSize:", VirtualMemory::VMSIZE},
43 {"VmHWM:", VirtualMemory::VMHWM}, {"VmRSS:", VirtualMemory::VMRSS},
44 {"VmStk:", VirtualMemory::VMSTK}, {"VmData:", VirtualMemory::VMDATA},
45 {"VmExe:", VirtualMemory::VMEXE}, {"VmLck:", VirtualMemory::VMLCK},
46 {"VmPin:", VirtualMemory::VMPIN}, {"VmLib:", VirtualMemory::VMLIB},
47 {"VmPTE:", VirtualMemory::VMPTE}, {"VmPMD:", VirtualMemory::VMPMD},
48 {"VmSwap:", VirtualMemory::VMSWAP}};
49
50 vmem_m.resize(procinfo_m.size());
51 unit_m.resize(procinfo_m.size());
52}
53
55 if (this->hasColumns()) {
56 return;
57 }
58
59 columns_m.addColumn("t", "double", "ns", "Time");
60
61 columns_m.addColumn("s", "double", "m", "Path length");
62
63 // peak virtual memory size
65 "VmPeak-Min", "double", unit_m[VirtualMemory::VMPEAK],
66 "Minimum peak virtual memory size");
67
69 "VmPeak-Max", "double", unit_m[VirtualMemory::VMPEAK],
70 "Maximum peak virtual memory size");
71
73 "VmPeak-Avg", "double", unit_m[VirtualMemory::VMPEAK],
74 "Average peak virtual memory size");
75
76 // virtual memory size
78 "VmSize-Min", "double", unit_m[VirtualMemory::VMSIZE], "Minimum virtual memory size");
79
81 "VmSize-Max", "double", unit_m[VirtualMemory::VMSIZE], "Maximum virtual memory size");
82
84 "VmSize-Avg", "double", unit_m[VirtualMemory::VMSIZE], "Average virtual memory size");
85
86 // peak resident set size ("high water mark")
88 "VmHWM-Min", "double", unit_m[VirtualMemory::VMHWM], "Minimum peak resident set size");
89
91 "VmHWM-Max", "double", unit_m[VirtualMemory::VMHWM], "Maximum peak resident set size");
92
94 "VmHWM-Avg", "double", unit_m[VirtualMemory::VMHWM], "Average peak resident set size");
95
96 // resident set size
98 "VmRSS-Min", "double", unit_m[VirtualMemory::VMRSS], "Minimum resident set size");
99
101 "VmRSS-Max", "double", unit_m[VirtualMemory::VMRSS], "Maximum resident set size");
102
104 "VmRSS-Avg", "double", unit_m[VirtualMemory::VMRSS], "Average resident set size");
105
106 // stack size
107 columns_m.addColumn("VmStk-Min", "double", unit_m[VirtualMemory::VMSTK], "Minimum stack size");
108
109 columns_m.addColumn("VmStk-Max", "double", unit_m[VirtualMemory::VMSTK], "Maximum stack size");
110
111 columns_m.addColumn("VmStk-Avg", "double", unit_m[VirtualMemory::VMSTK], "Average stack size");
112
113 if (mode_m == std::ios::app) return;
114
115 OPALTimer::Timer simtimer;
116
117 std::string dateStr(simtimer.date());
118 std::string timeStr(simtimer.time());
119
120 std::stringstream ss;
121 ss << "Memory statistics '" << OpalData::getInstance()->getInputFn() << "' " << dateStr << ""
122 << timeStr;
123
124 this->addDescription(ss.str(), "memory info");
125
126 this->addDefaultParameters();
127
128 this->addInfo("ascii", 1);
129}
130
132#ifdef __linux__
133 static pid_t pid = getpid();
134 std::string fname = "/proc/" + std::to_string(pid) + "/status";
135
136 if (!std::filesystem::exists(fname)) {
137 throw OpalException("MemoryProfiler::update()", "File '" + fname + "' doesn't exist.");
138 }
139
140 std::ifstream ifs(fname.c_str());
141
142 if (!ifs.is_open()) {
143 throw OpalException("MemoryProfiler::update()", "Failed to open '" + fname + "'.");
144 }
145
146 std::string token;
147 while (ifs >> token) {
148 if (!procinfo_m.count(token)) {
149 continue;
150 }
151 int idx = procinfo_m[token];
152 ifs >> vmem_m[idx] >> unit_m[idx];
153 }
154
155 ifs.close();
156#endif
157}
158
159void MemoryProfiler::compute(vm_t& vmMin, vm_t& vmMax, vm_t& vmAvg) {
160 if (ippl::Comm->size() == 1) {
161 for (unsigned int i = 0; i < vmem_m.size(); ++i) {
162 vmMin[i] = vmMax[i] = vmAvg[i] = vmem_m[i];
163 }
164 return;
165 }
166
167 // \fixme new_reduce(vmem_m.data(), vmAvg.data(), vmem_m.size(), std::plus<double>());
168 reduce(vmem_m.data(), vmAvg.data(), vmem_m.size(), std::plus<double>());
169
170 double inodes = 1.0 / double(ippl::Comm->size());
171 for (auto& vm : vmAvg) {
172 vm *= inodes;
173 }
174
175 // new_reduce(vmem_m.data(), vmMin.data(), vmem_m.size(), std::less<double>());
176 // new_reduce(vmem_m.data(), vmMax.data(), vmem_m.size(), std::greater<double>());
177 reduce(vmem_m.data(), vmMin.data(), vmem_m.size(), std::less<double>());
178 reduce(vmem_m.data(), vmMax.data(), vmem_m.size(), std::greater<double>());
179}
180
182 this->update();
183
184 vm_t vmMin(vmem_m.size());
185 vm_t vmMax(vmem_m.size());
186 vm_t vmAvg(vmem_m.size());
187
188 this->compute(vmMin, vmMax, vmAvg);
189
190 if (ippl::Comm->rank() != 0) {
191 return;
192 }
193
194 double pathLength = beam.getParticleContainers()[0]->get_sPos();
195
196 header();
197
198 this->open();
199
200 this->writeHeader();
201
202 columns_m.addColumnValue("t", beam.getT() * Units::s2ns); // 1
203 columns_m.addColumnValue("s", pathLength); // 2
204
205 // std::variant can't overload double and long double. By using a
206 // string this shortcoming can be bypassed.
207 columns_m.addColumnValue("VmPeak-Min", toString(vmMin[VMPEAK]));
208 columns_m.addColumnValue("VmPeak-Max", toString(vmMax[VMPEAK]));
209 columns_m.addColumnValue("VmPeak-Avg", toString(vmAvg[VMPEAK]));
210
211 columns_m.addColumnValue("VmSize-Min", toString(vmMin[VMSIZE]));
212 columns_m.addColumnValue("VmSize-Max", toString(vmMax[VMSIZE]));
213 columns_m.addColumnValue("VmSize-Avg", toString(vmAvg[VMSIZE]));
214
215 columns_m.addColumnValue("VmHWM-Min", toString(vmMin[VMHWM]));
216 columns_m.addColumnValue("VmHWM-Max", toString(vmMax[VMHWM]));
217 columns_m.addColumnValue("VmHWM-Avg", toString(vmAvg[VMHWM]));
218
219 columns_m.addColumnValue("VmRSS-Min", toString(vmMin[VMRSS]));
220 columns_m.addColumnValue("VmRSS-Max", toString(vmMax[VMRSS]));
221 columns_m.addColumnValue("VmRSS-Avg", toString(vmAvg[VMRSS]));
222
223 columns_m.addColumnValue("VmStk-Min", toString(vmMin[VMSTK]));
224 columns_m.addColumnValue("VmStk-Max", toString(vmMax[VMSTK]));
225 columns_m.addColumnValue("VmStk-Avg", toString(vmAvg[VMSTK]));
226
227 this->writeRow();
228
229 this->close();
230}
Template PIC bunch: IPPL PicManager, shared field mesh/solver, and multiple particle containers.
void compute(vm_t &vmMin, vm_t &vmMax, vm_t &vmAvg)
std::vector< long double > vm_t
void write(const PartBunch_t &beam) override
MemoryProfiler(const std::string &fname, bool restart)
std::map< std::string, int > procinfo_m
std::string time() const
Return time.
Definition Timer.cpp:36
std::string date() const
Return date.
Definition Timer.cpp:30
std::string getInputFn()
get opals input filename
Definition OpalData.cpp:569
static OpalData * getInstance()
Definition OpalData.cpp:193
double getT() const
Get the current simulation time.
Definition PartBunch.h:651
void addColumn(const std::string &name, const std::string &type, const std::string &unit, const std::string &desc, std::ios_base::fmtflags flags=std::ios_base::scientific, unsigned short precision=15)
void addColumnValue(const std::string &name, const T &val)
std::string toString(const T &val)
Definition SDDSWriter.h:161
SDDSColumnSet columns_m
Definition SDDSWriter.h:111
bool hasColumns() const
Definition SDDSWriter.h:168
void addDefaultParameters()
void addDescription(const std::string &text, const std::string &content)
Definition SDDSWriter.h:141
void writeHeader()
Write SDDS header.
std::ios_base::openmode mode_m
First write to the statistics output file.
Definition SDDSWriter.h:109
void writeRow()
Definition SDDSWriter.h:158
void addInfo(const std::string &mode, const size_t &no_row_counts)
Definition SDDSWriter.h:154
constexpr double s2ns
Definition Units.h:44