CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
CPU.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: Services
4 // Class : CPU
5 //
6 // Implementation:
7 //
8 // Original Author: Natalia Garcia
9 // CPU.cc: v 1.0 2009/01/08 11:31:07
10 
12 
20 
21 #include <iostream>
22 #include <sys/time.h>
23 #include <sys/resource.h>
24 #include <cstdio>
25 #include <string>
26 #include <fstream>
27 #include <sstream>
28 #include <set>
29 
30 #ifdef __linux__
31 #include <sched.h>
32 #include <cerrno>
33 #endif
34 
35 namespace edm {
36 
37  namespace service {
38  class CPU : public CPUServiceBase {
39  public:
40  CPU(ParameterSet const &, ActivityRegistry &);
41  ~CPU() override;
42 
43  static void fillDescriptions(ConfigurationDescriptions &descriptions);
44 
45  bool cpuInfo(std::string &models, double &avgSpeed) override;
46 
47  private:
49 
50  bool cpuInfoImpl(std::string &models, double &avgSpeed, Service<JobReport> *reportSvc);
51  bool parseCPUInfo(std::vector<std::pair<std::string, std::string>> &info);
52  std::string getModels(const std::vector<std::pair<std::string, std::string>> &info);
53  double getAverageSpeed(const std::vector<std::pair<std::string, std::string>> &info);
54  void postEndJob();
55  };
56 
57  inline bool isProcessWideService(CPU const *) { return true; }
58  } // namespace service
59 } // namespace edm
60 
61 namespace edm {
62  namespace service {
63  namespace {
64 
65  std::string i2str(int i) {
66  std::ostringstream t;
67  t << i;
68  return t.str();
69  }
70 
71  std::string d2str(double d) {
72  std::ostringstream t;
73  t << d;
74  return t.str();
75  }
76 
77  double str2d(std::string s) { return atof(s.c_str()); }
78 
79  void trim(std::string &s, const std::string &drop = " \t") {
80  std::string::size_type p = s.find_last_not_of(drop);
81  if (p != std::string::npos) {
82  s = s.erase(p + 1);
83  }
84  s = s.erase(0, s.find_first_not_of(drop));
85  }
86 
87  std::string eraseExtraSpaces(std::string s) {
88  bool founded = false;
90  for (std::string::const_iterator iter = s.begin(); iter != s.end(); iter++) {
91  if (founded) {
92  if (*iter == ' ')
93  founded = true;
94  else {
95  aux += " ";
96  aux += *iter;
97  founded = false;
98  }
99  } else {
100  if (*iter == ' ')
101  founded = true;
102  else
103  aux += *iter;
104  }
105  }
106  return aux;
107  }
108 
109  // Determine the CPU set size; if this can be successfully determined, then this
110  // returns true.
111  bool getCpuSetSize(unsigned &set_size) {
112 #ifdef __linux__
113  cpu_set_t *cpusetp;
114  unsigned current_size = 128;
115  unsigned cpu_count = 0;
116  while (current_size * 2 > current_size) {
117  cpusetp = CPU_ALLOC(current_size);
118  CPU_ZERO_S(CPU_ALLOC_SIZE(current_size), cpusetp);
119 
120  if (sched_getaffinity(0, CPU_ALLOC_SIZE(current_size), cpusetp)) {
121  CPU_FREE(cpusetp);
122  if (errno == EINVAL) {
123  current_size *= 2;
124  continue;
125  }
126  return false;
127  }
128  cpu_count = CPU_COUNT_S(CPU_ALLOC_SIZE(current_size), cpusetp);
129  CPU_FREE(cpusetp);
130  break;
131  }
132  set_size = cpu_count;
133  return true;
134 #else
135  return false;
136 #endif
137  }
138  } // namespace
139 
140  CPU::CPU(const ParameterSet &iPS, ActivityRegistry &iRegistry)
141  : reportCPUProperties_(iPS.getUntrackedParameter<bool>("reportCPUProperties")) {
142  iRegistry.watchPostEndJob(this, &CPU::postEndJob);
143  }
144 
146 
149  desc.addUntracked<bool>("reportCPUProperties", false);
150  descriptions.add("CPU", desc);
151  }
152 
154  Service<JobReport> reportSvc;
155 
156  std::vector<std::pair<std::string, std::string>> info;
157  if (!parseCPUInfo(info)) {
158  return;
159  }
160 
161  std::string models = getModels(info);
162  double avgSpeed = getAverageSpeed(info);
163  unsigned totalNumberCPUs = 0;
164  std::map<std::string, std::string> currentCoreProperties;
165  std::string currentCore;
166 
167  for (const auto &entry : info) {
168  if (entry.first == "processor") {
169  if (reportCPUProperties_) {
170  if (currentCore.empty()) { // first core
171  currentCore = entry.second;
172  } else {
173  reportSvc->reportPerformanceForModule("SystemCPU", "CPU-" + currentCore, currentCoreProperties);
174  currentCoreProperties.clear();
175  currentCore = entry.second;
176  }
177  }
178  totalNumberCPUs++;
179  } else if (reportCPUProperties_) {
180  currentCoreProperties.insert(entry);
181  }
182  }
183  if (!currentCore.empty() && reportCPUProperties_) {
184  reportSvc->reportPerformanceForModule("SystemCPU", "CPU-" + currentCore, currentCoreProperties);
185  }
186 
187  std::map<std::string, std::string> reportCPUProperties{
188  {"totalCPUs", i2str(totalNumberCPUs)}, {"averageCoreSpeed", d2str(avgSpeed)}, {"CPUModels", models}};
189  unsigned set_size = -1;
190  if (getCpuSetSize(set_size)) {
191  reportCPUProperties.insert(std::make_pair("cpusetCount", i2str(set_size)));
192  }
193  reportSvc->reportPerformanceSummary("SystemCPU", reportCPUProperties);
194  }
195 
196  bool CPU::cpuInfo(std::string &models, double &avgSpeed) {
197  std::vector<std::pair<std::string, std::string>> info;
198  if (!parseCPUInfo(info)) {
199  return false;
200  }
201 
202  models = getModels(info);
203  avgSpeed = getAverageSpeed(info);
204  return true;
205  }
206 
207  bool CPU::parseCPUInfo(std::vector<std::pair<std::string, std::string>> &info) {
208  info.clear();
209  std::ifstream fcpuinfo("/proc/cpuinfo");
210  if (!fcpuinfo.is_open()) {
211  return false;
212  }
213  while (!fcpuinfo.eof()) {
215  std::getline(fcpuinfo, buf);
216 
217  std::istringstream iss(buf);
219  std::string property;
221 
222  int time = 1;
223 
224  while (std::getline(iss, token, ':')) {
225  switch (time) {
226  case 1:
227  property = token;
228  break;
229  case 2:
230  value = token;
231  break;
232  default:
233  value += token;
234  break;
235  }
236  time++;
237  }
238  trim(property);
239  trim(value);
240  if (property.empty()) {
241  continue;
242  }
243 
244  if (property == "model name") {
245  value = eraseExtraSpaces(value);
246  }
247  info.emplace_back(property, value);
248  }
249  return true;
250  }
251 
252  std::string CPU::getModels(const std::vector<std::pair<std::string, std::string>> &info) {
253  std::set<std::string> models;
254  for (const auto &entry : info) {
255  if (entry.first == "model name") {
256  models.insert(entry.second);
257  }
258  }
259  std::stringstream ss;
260  int model = 0;
261  for (const auto &modelname : models) {
262  if (model++ != 0) {
263  ss << ", ";
264  }
265  ss << modelname;
266  }
267  return ss.str();
268  }
269 
270  double CPU::getAverageSpeed(const std::vector<std::pair<std::string, std::string>> &info) {
271  double averageCoreSpeed = 0.0;
272  unsigned coreCount = 0;
273  for (const auto &entry : info) {
274  if (entry.first == "cpu MHz") {
275  averageCoreSpeed += str2d(entry.second);
276  coreCount++;
277  }
278  }
279  if (!coreCount) {
280  return 0;
281  }
282  return averageCoreSpeed / static_cast<double>(coreCount);
283  }
284  } // namespace service
285 } // namespace edm
286 
287 using edm::service::CPU;
static std::string i2str(int i)
static const TGPicture * info(bool iBackgroundIsBlack)
double getAverageSpeed(const std::vector< std::pair< std::string, std::string >> &info)
Definition: CPU.cc:270
#define DEFINE_FWK_SERVICE_MAKER(concrete, maker)
Definition: ServiceMaker.h:100
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void postEndJob()
Definition: CPU.cc:153
void watchPostEndJob(PostEndJob::slot_type const &iSlot)
bool isProcessWideService(TFileService const *)
Definition: TFileService.h:98
static void trim(std::string &s)
uint16_t size_type
edm::serviceregistry::AllArgsMaker< edm::CPUServiceBase, CPU > CPUMaker
Definition: CPU.cc:288
tuple d
Definition: ztail.py:151
bool cpuInfo(std::string &models, double &avgSpeed) override
CPU information - the models present and average speed.
Definition: CPU.cc:196
bool parseCPUInfo(std::vector< std::pair< std::string, std::string >> &info)
Definition: CPU.cc:207
~CPU() override
Definition: CPU.cc:145
const int drop
CPU(ParameterSet const &, ActivityRegistry &)
Definition: CPU.cc:140
static std::string d2str(double d)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
bool cpuInfoImpl(std::string &models, double &avgSpeed, Service< JobReport > *reportSvc)
static void fillDescriptions(ConfigurationDescriptions &descriptions)
Definition: CPU.cc:147
list entry
Definition: mps_splice.py:68
const bool reportCPUProperties_
Definition: CPU.cc:48
std::string getModels(const std::vector< std::pair< std::string, std::string >> &info)
Definition: CPU.cc:252