Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / mkldnn_plugin / mkldnn / os / lin / lin_omp_manager.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "lin_omp_manager.h"
6 #include <fstream>
7 #include <set>
8 #include <string>
9 #include <vector>
10 #include <iostream>
11
12 namespace MKLDNNPlugin {
13 namespace cpu {
14
15 #ifndef __APPLE__
16
17 Processor::Processor() {
18     processor = 0;
19     physicalId = 0;
20     cpuCores = 0;
21 }
22
23 CpuInfo::CpuInfo() {
24     loadContentFromFile("/proc/cpuinfo");
25 }
26
27 void CpuInfo::loadContentFromFile(const char *fileName) {
28     std::ifstream file(fileName);
29     std::string content(
30             (std::istreambuf_iterator<char>(file)),
31             (std::istreambuf_iterator<char>()));
32
33     loadContent(content.c_str());
34 }
35
36 void CpuInfo::loadContent(const char *content) {
37     size_t contentLength = strlen(content);
38     char *contentCopy = new char[contentLength + 1];
39     snprintf(contentCopy, contentLength + 1, "%s", content);
40
41     parseLines(contentCopy);
42
43     fileContentBegin = contentCopy;
44     fileContentEnd = &contentCopy[contentLength];
45     currentLine = NULL;
46 }
47
48 CpuInfo::~CpuInfo() {
49     delete[] fileContentBegin;
50 }
51
52 void CpuInfo::parseLines(char *content) {
53     for (; *content; content++) {
54         if (*content == '\n') {
55             *content = '\0';
56         }
57     }
58 }
59
60 const char *CpuInfo::getFirstLine() {
61     currentLine = fileContentBegin < fileContentEnd ? fileContentBegin : NULL;
62     return getNextLine();
63 }
64
65 const char *CpuInfo::getNextLine() {
66     if (!currentLine) {
67         return NULL;
68     }
69
70     const char *savedCurrentLine = currentLine;
71     while (*(currentLine++)) {
72     }
73
74     if (currentLine >= fileContentEnd) {
75         currentLine = NULL;
76     }
77
78     return savedCurrentLine;
79 }
80
81 Collection::Collection(CpuInfoInterface *cpuInfo) : cpuInfo(*cpuInfo) {
82     totalNumberOfSockets = 0;
83     totalNumberOfCpuCores = 0;
84     currentProcessor = NULL;
85
86     processors.reserve(96);
87
88     parseCpuInfo();
89     collectBasicCpuInformation();
90 }
91
92 unsigned Collection::getTotalNumberOfSockets() {
93     return totalNumberOfSockets;
94 }
95
96 unsigned Collection::getTotalNumberOfCpuCores() {
97     return totalNumberOfCpuCores;
98 }
99
100 unsigned Collection::getNumberOfProcessors() {
101     return processors.size();
102 }
103
104 void Collection::parseCpuInfo() {
105     const char *cpuInfoLine = cpuInfo.getFirstLine();
106     for (; cpuInfoLine; cpuInfoLine = cpuInfo.getNextLine()) {
107         parseCpuInfoLine(cpuInfoLine);
108     }
109 }
110
111 void Collection::parseCpuInfoLine(const char *cpuInfoLine) {
112     int delimiterPosition = strcspn(cpuInfoLine, ":");
113
114     if (cpuInfoLine[delimiterPosition] == '\0') {
115         currentProcessor = NULL;
116     } else {
117         parseValue(cpuInfoLine, &cpuInfoLine[delimiterPosition + 2]);
118     }
119 }
120
121 void Collection::parseValue(const char *fieldName, const char *valueString) {
122     if (!currentProcessor) {
123         appendNewProcessor();
124     }
125
126     if (beginsWith(fieldName, "processor")) {
127         currentProcessor->processor = parseInteger(valueString);
128     }
129
130     if (beginsWith(fieldName, "physical id")) {
131         currentProcessor->physicalId = parseInteger(valueString);
132     }
133
134     if (beginsWith(fieldName, "cpu cores")) {
135         currentProcessor->cpuCores = parseInteger(valueString);
136     }
137 }
138
139 void Collection::appendNewProcessor() {
140     processors.push_back(Processor());
141     currentProcessor = &processors.back();
142 }
143
144 bool Collection::beginsWith(const char *lineBuffer, const char *text) const {
145     while (*text) {
146         if (*(lineBuffer++) != *(text++)) {
147             return false;
148         }
149     }
150
151     return true;
152 }
153
154 unsigned Collection::parseInteger(const char *text) const {
155     return atol(text);
156 }
157
158 void Collection::collectBasicCpuInformation() {
159     std::set<unsigned> uniquePhysicalId;
160     std::vector<Processor>::iterator processor = processors.begin();
161     for (; processor != processors.end(); processor++) {
162         uniquePhysicalId.insert(processor->physicalId);
163         updateCpuInformation(*processor, uniquePhysicalId.size());
164     }
165 }
166
167 void Collection::updateCpuInformation(const Processor &processor,
168                                       unsigned numberOfUniquePhysicalId) {
169     if (totalNumberOfSockets == numberOfUniquePhysicalId) {
170         return;
171     }
172
173     totalNumberOfSockets = numberOfUniquePhysicalId;
174     totalNumberOfCpuCores += processor.cpuCores;
175 }
176
177 #include <sched.h>
178
179 int getNumberOfCPUSockets() {
180     static CpuInfo cpuInfo;
181     static Collection collection(&cpuInfo);
182     return collection.getTotalNumberOfSockets();
183 }
184
185 int getNumberOfCPUCores() {
186     static CpuInfo cpuInfo;
187     static Collection collection(&cpuInfo);
188     unsigned numberOfProcessors = collection.getNumberOfProcessors();
189     unsigned totalNumberOfCpuCores = collection.getTotalNumberOfCpuCores();
190
191     cpu_set_t usedCoreSet, currentCoreSet, currentCpuSet;
192     CPU_ZERO(&currentCpuSet);
193     CPU_ZERO(&usedCoreSet);
194     CPU_ZERO(&currentCoreSet);
195
196     sched_getaffinity(0, sizeof(currentCpuSet), &currentCpuSet);
197
198     for (int processorId = 0; processorId < numberOfProcessors; processorId++) {
199         if (CPU_ISSET(processorId, &currentCpuSet)) {
200             unsigned coreId = processorId % totalNumberOfCpuCores;
201             if (!CPU_ISSET(coreId, &usedCoreSet)) {
202                 CPU_SET(coreId, &usedCoreSet);
203                 CPU_SET(processorId, &currentCoreSet);
204             }
205         }
206     }
207     return CPU_COUNT(&currentCoreSet);
208 }
209
210 #endif  // #ifndef APPLE
211 }  // namespace cpu
212 }  // namespace MKLDNNPlugin