Skip to content

Commit

Permalink
Merge pull request #40441 from dan131riley/resourceInformationService…
Browse files Browse the repository at this point in the history
…-non-intel

Update CPU service calls to ResourceInformationService  for non-Intel CPUs
  • Loading branch information
cmsbuild committed Jan 10, 2023
2 parents 8ba73db + 3df8ae5 commit 6593af1
Showing 1 changed file with 46 additions and 74 deletions.
120 changes: 46 additions & 74 deletions FWCore/Services/plugins/CPU.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// CPU.cc: v 1.0 2009/01/08 11:31:07

#include "FWCore/MessageLogger/interface/JobReport.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
Expand Down Expand Up @@ -45,23 +46,25 @@
#endif

namespace edm {
using CPUInfoType = std::vector<std::pair<std::string, std::string>>;

namespace service {
class CPU : public CPUServiceBase {
public:
CPU(ParameterSet const &, ActivityRegistry &);
~CPU() override;
~CPU() override = default;

static void fillDescriptions(ConfigurationDescriptions &descriptions);

private:
const bool reportCPUProperties_;
const bool disableJobReportOutput_;

bool parseCPUInfo(std::vector<std::pair<std::string, std::string>> &info);
std::string getModels(const std::vector<std::pair<std::string, std::string>> &info);
std::string getModelFromCPUFeatures();
double getAverageSpeed(const std::vector<std::pair<std::string, std::string>> &info);
bool parseCPUInfo(CPUInfoType &info) const;
std::vector<std::string> getModels(const CPUInfoType &info) const;
std::string formatModels(const std::vector<std::string> &models) const;
std::string getModelFromCPUFeatures() const;
double getAverageSpeed(const CPUInfoType &info) const;
void postEndJob();
};

Expand All @@ -73,20 +76,6 @@ namespace edm {
namespace service {
namespace {

std::string i2str(int i) {
std::ostringstream t;
t << i;
return t.str();
}

std::string d2str(double d) {
std::ostringstream t;
t << d;
return t.str();
}

double str2d(std::string s) { return atof(s.c_str()); }

void trim(std::string &s, const std::string &drop = " \t") {
std::string::size_type p = s.find_last_not_of(drop);
if (p != std::string::npos) {
Expand All @@ -95,26 +84,10 @@ namespace edm {
s = s.erase(0, s.find_first_not_of(drop));
}

std::string eraseExtraSpaces(std::string s) {
bool founded = false;
std::string aux;
for (std::string::const_iterator iter = s.begin(); iter != s.end(); iter++) {
if (founded) {
if (*iter == ' ')
founded = true;
else {
aux += " ";
aux += *iter;
founded = false;
}
} else {
if (*iter == ' ')
founded = true;
else
aux += *iter;
}
}
return aux;
void compressWhitespace(std::string &s) {
auto last =
std::unique(s.begin(), s.end(), [](const auto a, const auto b) { return std::isspace(a) && a == b; });
s.erase(last, s.end());
}

// Determine the CPU set size; if this can be successfully determined, then this
Expand Down Expand Up @@ -153,28 +126,17 @@ namespace edm {
disableJobReportOutput_(iPS.getUntrackedParameter<bool>("disableJobReportOutput")) {
edm::Service<edm::ResourceInformation> resourceInformationService;
if (resourceInformationService.isAvailable()) {
std::vector<std::pair<std::string, std::string>> info;
CPUInfoType info;
if (parseCPUInfo(info)) {
std::string models = getModels(info);
double averageSpeed = getAverageSpeed(info);
resourceInformationService->setCpuModelsFormatted(models);
resourceInformationService->setCpuAverageSpeed(averageSpeed);

std::set<std::string> modelsSet;
for (const auto &entry : info) {
if (entry.first == "model name") {
modelsSet.insert(entry.second);
}
}
std::vector<std::string> modelsVector(modelsSet.begin(), modelsSet.end());
resourceInformationService->setCPUModels(modelsVector);
const auto models{getModels(info)};
resourceInformationService->setCPUModels(models);
resourceInformationService->setCpuModelsFormatted(formatModels(models));
resourceInformationService->setCpuAverageSpeed(getAverageSpeed(info));
}
}
iRegistry.watchPostEndJob(this, &CPU::postEndJob);
}

CPU::~CPU() {}

void CPU::fillDescriptions(edm::ConfigurationDescriptions &descriptions) {
edm::ParameterSetDescription desc;
desc.addUntracked<bool>("reportCPUProperties", false);
Expand All @@ -189,13 +151,12 @@ namespace edm {

Service<JobReport> reportSvc;

std::vector<std::pair<std::string, std::string>> info;
CPUInfoType info;
if (!parseCPUInfo(info)) {
return;
}

std::string models = getModels(info);
double avgSpeed = getAverageSpeed(info);
const auto models{formatModels(getModels(info))};
unsigned totalNumberCPUs = 0;
std::map<std::string, std::string> currentCoreProperties;
std::string currentCore;
Expand All @@ -221,15 +182,17 @@ namespace edm {
}

std::map<std::string, std::string> reportCPUProperties{
{"totalCPUs", i2str(totalNumberCPUs)}, {"averageCoreSpeed", d2str(avgSpeed)}, {"CPUModels", models}};
{"totalCPUs", std::to_string(totalNumberCPUs)},
{"averageCoreSpeed", std::to_string(getAverageSpeed(info))},
{"CPUModels", models}};
unsigned set_size = -1;
if (getCpuSetSize(set_size)) {
reportCPUProperties.insert(std::make_pair("cpusetCount", i2str(set_size)));
reportCPUProperties.insert(std::make_pair("cpusetCount", std::to_string(set_size)));
}
reportSvc->reportPerformanceSummary("SystemCPU", reportCPUProperties);
}

bool CPU::parseCPUInfo(std::vector<std::pair<std::string, std::string>> &info) {
bool CPU::parseCPUInfo(CPUInfoType &info) const {
info.clear();
std::ifstream fcpuinfo("/proc/cpuinfo");
if (!fcpuinfo.is_open()) {
Expand Down Expand Up @@ -267,14 +230,14 @@ namespace edm {
}

if (property == "model name") {
value = eraseExtraSpaces(value);
compressWhitespace(value);
}
info.emplace_back(property, value);
}
return true;
}

std::string CPU::getModelFromCPUFeatures() {
std::string CPU::getModelFromCPUFeatures() const {
using namespace cpu_features;

std::string model;
Expand All @@ -294,13 +257,23 @@ namespace edm {
return model;
}

std::string CPU::getModels(const std::vector<std::pair<std::string, std::string>> &info) {
std::set<std::string> models;
std::vector<std::string> CPU::getModels(const CPUInfoType &info) const {
std::set<std::string> modelSet;
for (const auto &entry : info) {
if (entry.first == "model name") {
models.insert(entry.second);
modelSet.insert(entry.second);
}
}
std::vector<std::string> modelsVector(modelSet.begin(), modelSet.end());
// If "model name" isn't present in /proc/cpuinfo, see what we can get
// from cpu_features
if (modelsVector.empty()) {
modelsVector.emplace_back(getModelFromCPUFeatures());
}
return modelsVector;
}

std::string CPU::formatModels(const std::vector<std::string> &models) const {
std::stringstream ss;
int model = 0;
for (const auto &modelname : models) {
Expand All @@ -309,20 +282,19 @@ namespace edm {
}
ss << modelname;
}
// If "model name" isn't present in /proc/cpuinfo, see what we can get
// from cpu_features
if (0 == model) {
return getModelFromCPUFeatures();
}
return ss.str();
}

double CPU::getAverageSpeed(const std::vector<std::pair<std::string, std::string>> &info) {
double CPU::getAverageSpeed(const CPUInfoType &info) const {
double averageCoreSpeed = 0.0;
unsigned coreCount = 0;
for (const auto &entry : info) {
if (entry.first == "cpu MHz") {
averageCoreSpeed += str2d(entry.second);
try {
averageCoreSpeed += std::stod(entry.second);
} catch (const std::logic_error &e) {
LogWarning("CPU::getAverageSpeed") << "stod(" << entry.second << ") conversion error: " << e.what();
}
coreCount++;
}
}
Expand All @@ -337,5 +309,5 @@ namespace edm {
#include "FWCore/ServiceRegistry/interface/ServiceMaker.h"

using edm::service::CPU;
typedef edm::serviceregistry::AllArgsMaker<edm::CPUServiceBase, CPU> CPUMaker;
using CPUMaker = edm::serviceregistry::AllArgsMaker<edm::CPUServiceBase, CPU>;
DEFINE_FWK_SERVICE_MAKER(CPU, CPUMaker);

0 comments on commit 6593af1

Please sign in to comment.