OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
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 <boost/filesystem.hpp>
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
64 columns_m.addColumn(
65 "VmPeak-Min", "double", unit_m[VirtualMemory::VMPEAK], "Minimum peak virtual memory size");
66
67 columns_m.addColumn(
68 "VmPeak-Max", "double", unit_m[VirtualMemory::VMPEAK], "Maximum peak virtual memory size");
69
70 columns_m.addColumn(
71 "VmPeak-Avg", "double", unit_m[VirtualMemory::VMPEAK], "Average peak virtual memory size");
72
73 // virtual memory size
74 columns_m.addColumn(
75 "VmSize-Min", "double", unit_m[VirtualMemory::VMSIZE], "Minimum virtual memory size");
76
77 columns_m.addColumn(
78 "VmSize-Max", "double", unit_m[VirtualMemory::VMSIZE], "Maximum virtual memory size");
79
80 columns_m.addColumn(
81 "VmSize-Avg", "double", unit_m[VirtualMemory::VMSIZE], "Average virtual memory size");
82
83 // peak resident set size ("high water mark")
84 columns_m.addColumn(
85 "VmHWM-Min", "double", unit_m[VirtualMemory::VMHWM], "Minimum peak resident set size");
86
87 columns_m.addColumn(
88 "VmHWM-Max", "double", unit_m[VirtualMemory::VMHWM], "Maximum peak resident set size");
89
90 columns_m.addColumn(
91 "VmHWM-Avg", "double", unit_m[VirtualMemory::VMHWM], "Average peak resident set size");
92
93 // resident set size
94 columns_m.addColumn(
95 "VmRSS-Min", "double", unit_m[VirtualMemory::VMRSS], "Minimum resident set size");
96
97 columns_m.addColumn(
98 "VmRSS-Max", "double", unit_m[VirtualMemory::VMRSS], "Maximum resident set size");
99
100 columns_m.addColumn(
101 "VmRSS-Avg", "double", unit_m[VirtualMemory::VMRSS], "Average resident set size");
102
103 // stack size
104 columns_m.addColumn("VmStk-Min", "double", unit_m[VirtualMemory::VMSTK], "Minimum stack size");
105
106 columns_m.addColumn("VmStk-Max", "double", unit_m[VirtualMemory::VMSTK], "Maximum stack size");
107
108 columns_m.addColumn("VmStk-Avg", "double", unit_m[VirtualMemory::VMSTK], "Average stack size");
109
110 if (mode_m == std::ios::app)
111 return;
112
113 OPALTimer::Timer simtimer;
114
115 std::string dateStr(simtimer.date());
116 std::string timeStr(simtimer.time());
117
118 std::stringstream ss;
119 ss << "Memory statistics '" << OpalData::getInstance()->getInputFn() << "' " << dateStr << ""
120 << timeStr;
121
122 this->addDescription(ss.str(), "memory info");
123
124 this->addDefaultParameters();
125
126 this->addInfo("ascii", 1);
127}
128
130#ifdef __linux__
131 static pid_t pid = getpid();
132 std::string fname = "/proc/" + std::to_string(pid) + "/status";
133
134 if (!boost::filesystem::exists(fname)) {
135 throw OpalException("MemoryProfiler::update()", "File '" + fname + "' doesn't exist.");
136 }
137
138 std::ifstream ifs(fname.c_str());
139
140 if (!ifs.is_open()) {
141 throw OpalException("MemoryProfiler::update()", "Failed to open '" + fname + "'.");
142 }
143
144 std::string token;
145 while (ifs >> token) {
146 if (!procinfo_m.count(token)) {
147 continue;
148 }
149 int idx = procinfo_m[token];
150 ifs >> vmem_m[idx] >> unit_m[idx];
151 }
152
153 ifs.close();
154#endif
155}
156
157void MemoryProfiler::compute(vm_t& vmMin, vm_t& vmMax, vm_t& vmAvg) {
158 if (ippl::Comm->size() == 1) {
159 for (unsigned int i = 0; i < vmem_m.size(); ++i) {
160 vmMin[i] = vmMax[i] = vmAvg[i] = vmem_m[i];
161 }
162 return;
163 }
164
165 // \fixme new_reduce(vmem_m.data(), vmAvg.data(), vmem_m.size(), std::plus<double>());
166 reduce(vmem_m.data(), vmAvg.data(), vmem_m.size(), std::plus<double>());
167
168 double inodes = 1.0 / double(ippl::Comm->size());
169 for (auto& vm : vmAvg) {
170 vm *= inodes;
171 }
172
173 //new_reduce(vmem_m.data(), vmMin.data(), vmem_m.size(), std::less<double>());
174 //new_reduce(vmem_m.data(), vmMax.data(), vmem_m.size(), std::greater<double>());
175 reduce(vmem_m.data(), vmMin.data(), vmem_m.size(), std::less<double>());
176 reduce(vmem_m.data(), vmMax.data(), vmem_m.size(), std::greater<double>());
177}
178
180 this->update();
181
182 vm_t vmMin(vmem_m.size());
183 vm_t vmMax(vmem_m.size());
184 vm_t vmAvg(vmem_m.size());
185
186 this->compute(vmMin, vmMax, vmAvg);
187
188 if (ippl::Comm->rank() != 0) {
189 return;
190 }
191
192 double pathLength = beam->get_sPos();
193
194 header();
195
196 this->open();
197
198 this->writeHeader();
199
200 columns_m.addColumnValue("t", beam->getT() * Units::s2ns); // 1
201 columns_m.addColumnValue("s", pathLength); // 2
202
203 // boost::variant can't overload double and long double. By using a
204 // string this shortcoming can be bypassed.
205 columns_m.addColumnValue("VmPeak-Min", toString(vmMin[VMPEAK]));
206 columns_m.addColumnValue("VmPeak-Max", toString(vmMax[VMPEAK]));
207 columns_m.addColumnValue("VmPeak-Avg", toString(vmAvg[VMPEAK]));
208
209 columns_m.addColumnValue("VmSize-Min", toString(vmMin[VMSIZE]));
210 columns_m.addColumnValue("VmSize-Max", toString(vmMax[VMSIZE]));
211 columns_m.addColumnValue("VmSize-Avg", toString(vmAvg[VMSIZE]));
212
213 columns_m.addColumnValue("VmHWM-Min", toString(vmMin[VMHWM]));
214 columns_m.addColumnValue("VmHWM-Max", toString(vmMax[VMHWM]));
215 columns_m.addColumnValue("VmHWM-Avg", toString(vmAvg[VMHWM]));
216
217 columns_m.addColumnValue("VmRSS-Min", toString(vmMin[VMRSS]));
218 columns_m.addColumnValue("VmRSS-Max", toString(vmMax[VMRSS]));
219 columns_m.addColumnValue("VmRSS-Avg", toString(vmAvg[VMRSS]));
220
221 columns_m.addColumnValue("VmStk-Min", toString(vmMin[VMSTK]));
222 columns_m.addColumnValue("VmStk-Max", toString(vmMax[VMSTK]));
223 columns_m.addColumnValue("VmStk-Avg", toString(vmAvg[VMSTK]));
224
225 this->writeRow();
226
227 this->close();
228}
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
constexpr double s2ns
Definition Units.h:44
std::string getInputFn()
get opals input filename
Definition OpalData.cpp:681
static OpalData * getInstance()
Definition OpalData.cpp:195
double get_sPos() const
double getT() const
void compute(vm_t &vmMin, vm_t &vmMax, vm_t &vmAvg)
std::vector< long double > vm_t
MemoryProfiler(const std::string &fname, bool restart)
std::map< std::string, int > procinfo_m
void write(const PartBunch_t *beam) override
SDDSWriter(const std::string &fname, bool restart)
std::string toString(const T &val)
Definition SDDSWriter.h:164
SDDSColumnSet columns_m
Definition SDDSWriter.h:110
bool hasColumns() const
Definition SDDSWriter.h:171
void addDefaultParameters()
void addDescription(const std::string &text, const std::string &content)
Definition SDDSWriter.h:142
void writeHeader()
Write SDDS header.
std::ios_base::openmode mode_m
First write to the statistics output file.
Definition SDDSWriter.h:108
void writeRow()
Definition SDDSWriter.h:159
void addInfo(const std::string &mode, const size_t &no_row_counts)
Definition SDDSWriter.h:155
The base class for all OPAL exceptions.
std::string time() const
Return time.
Definition Timer.cpp:42
std::string date() const
Return date.
Definition Timer.cpp:35