CMS 3D CMS Logo

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