A 机器上可以使用openvino
B 无法使用openvino
broadwell架构(支持avx-512)的cpu机器,系统配置文件/proc/cpuinfo中获取不到cpu cores
字段。
cpu cores
,而B获取不到getTotalNumberOfCpuCores()
函数最终调用Collection::parseValue()
函数解析linux系统文件/proc/cpuinfo
中的processor,physical id,cpu cores字段。而B的机器上可能因为是broadwell架构,/proc/cpuinfo
文件中不包含cpu cores字段,因此返回默认值0,导致在 getTotalNumberOfCpuCores()
函数调用unsigned coreId = processorId % totalNumberOfCpuCores;
这条语句时,由于除数为0,因此出现浮点数例外
,即SIGFPE - Floating point error signal
的错误。
void Collection::parseValue(const char *fieldName, const char *valueString) {
if (!currentProcessor) {
appendNewProcessor();
}
if (beginsWith(fieldName, "processor")) {
currentProcessor->processor = parseInteger(valueString);
}
if (beginsWith(fieldName, "physical id")) {
currentProcessor->physicalId = parseInteger(valueString);
}
if (beginsWith(fieldName, "cpu cores")) {
currentProcessor->cpuCores = parseInteger(valueString);
}
}
程序实际是如何根据“/proc/cpuinfo”
文件中的processor,physical id,cpu cores字段。,获取到最终的numberOfProcessors,totalNumberOfCpuCores和totalNumberOfSockets呢?
我们以正常机器A为例,看看这几个机器的processor,physical id,cpu cores字段字段分别是什么?
[root@A /opt/intel/openvino]# cat /proc/cpuinfo |grep "processor"
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
processor : 8
processor : 9
processor : 10
processor : 11
见注释:
unsigned Collection::getNumberOfProcessors() {
return processors.size(); // 3. 最终容器processors的size就是A这台机器的processor个数,numberOfProcessors = 12。
}
void Collection::parseCpuInfoLine(const char *cpuInfoLine) {
int delimiterPosition = strcspn(cpuInfoLine, ":");
if (cpuInfoLine[delimiterPosition] == '\0') { // 1. 碰到空行时,将currentProcessor设置为NULL
currentProcessor = NULL;
} else {
parseValue(cpuInfoLine, &cpuInfoLine[delimiterPosition + 2]);
}
}
void Collection::parseValue(const char *fieldName, const char *valueString) {
// 2. 调用currentProcessor->physicalId = parseInteger(valueString);解析physical id时,
// currentProcessor由于先碰到空行,被设置为NULL。因此会给新增一个元素到容器processors中。
if (!currentProcessor) {
appendNewProcessor();
}
if (beginsWith(fieldName, "processor")) {
currentProcessor->processor = parseInteger(valueString);
}
if (beginsWith(fieldName, "physical id")) {
currentProcessor->physicalId = parseInteger(valueString);
}
if (beginsWith(fieldName, "cpu cores")) {
currentProcessor->cpuCores = parseInteger(valueString);
}
}
void Collection::appendNewProcessor() {
processors.push_back(Processor());
currentProcessor = &processors.back();
}
[root@A /opt/intel/openvino]# cat /proc/cpuinfo |grep "physical id"
physical id : 0
physical id : 0
physical id : 0
physical id : 1
physical id : 1
physical id : 1
physical id : 2
physical id : 2
physical id : 2
physical id : 3
physical id : 3
physical id : 3
[root@A /opt/intel/openvino]# cat /proc/cpuinfo |grep "cpu cores"
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
cpu cores : 3
见注释:
void Collection::collectBasicCpuInformation() {
// 0. set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。Set中元素的值不能直接被改变。
std::set<unsigned> uniquePhysicalId;
std::vector<Processor>::iterator processor = processors.begin();
// 1. 根据processors的size=12对每一个processor->physicalId进行查询和判断。
for (; processor != processors.end(); processor++) {
// 2. 将12个processor中的physicalId都插入到容器std::set中
uniquePhysicalId.insert(processor->physicalId);
// 3. uniquePhysicalId.size()返回时不重复的元素的个数,
// 即将12个physical id = [0 0 0 1 1 1 2 2 2 3 3 3]不重复的元素个数求解出来。
updateCpuInformation(*processor, uniquePhysicalId.size());
}
}
void Collection::updateCpuInformation(const Processor &processor,
unsigned numberOfUniquePhysicalId) {
// 4. 例如,当processor取到第0个时,totalNumberOfSockets = numberOfUniquePhysicalId = 1,
// 当processor取到第1~2个时,totalNumberOfSockets == numberOfUniquePhysicalId,
// 因此将第1~2个processor的 physical id 和 对应的cpu cores 跳过,避免重复加和到totalNumberOfCpuCores上。
// 直到processor取到第3个,numberOfUniquePhysicalId = uniquePhysicalId.size()更新为2,重复以上操作。
if (totalNumberOfSockets == numberOfUniquePhysicalId) {
return;
}
// 5. 因此,totalNumberOfSockets 记录的是实际的物理cpu的个数,
// totalNumberOfCpuCores记录的是实际的cpu核数 = 物理cpu的个数 * [**cpu core**]
totalNumberOfSockets = numberOfUniquePhysicalId;
totalNumberOfCpuCores += processor.cpuCores; // 实际只加和了4次3.
}
第一章分析了,是因为B的机器上可能因为是broadwell架构,其/proc/cpuinfo
文件中不包含cpu cores字段,因此,虽然numberOfProcessors=12,但totalNumberOfCpuCores=0,因此可以对于broadwell架构机器,判断,如果totalNumberOfCpuCores==0,则将totalNumberOfCpuCores 设置为 numberOfProcessors。