Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CPU service calls to ResourceInformationService for non-Intel CPUs #40441

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);