changes thread ID mapping such that we first fill up all thread on one core */
| 174 | |
| 175 | /* changes thread ID mapping such that we first fill up all thread on one core */ |
| 176 | size_t mapThreadID(size_t threadID) |
| 177 | { |
| 178 | Lock<MutexSys> lock(mutex); |
| 179 | |
| 180 | if (threadIDs.size() == 0) |
| 181 | { |
| 182 | /* parse thread/CPU topology */ |
| 183 | for (size_t cpuID=0;;cpuID++) |
| 184 | { |
| 185 | std::fstream fs; |
| 186 | std::string cpu = std::string("/sys/devices/system/cpu/cpu") + std::to_string((long long)cpuID) + std::string("/topology/thread_siblings_list"); |
| 187 | fs.open (cpu.c_str(), std::fstream::in); |
| 188 | if (fs.fail()) break; |
| 189 | |
| 190 | int i; |
| 191 | while (fs >> i) |
| 192 | { |
| 193 | if (std::none_of(threadIDs.begin(),threadIDs.end(),[&] (int id) { return id == i; })) |
| 194 | threadIDs.push_back(i); |
| 195 | if (fs.peek() == ',') |
| 196 | fs.ignore(); |
| 197 | } |
| 198 | fs.close(); |
| 199 | } |
| 200 | |
| 201 | #if 0 |
| 202 | for (size_t i=0;i<threadIDs.size();i++) |
| 203 | std::cout << i << " -> " << threadIDs[i] << std::endl; |
| 204 | #endif |
| 205 | |
| 206 | /* verify the mapping and do not use it if the mapping has errors */ |
| 207 | for (size_t i=0;i<threadIDs.size();i++) { |
| 208 | for (size_t j=0;j<threadIDs.size();j++) { |
| 209 | if (i != j && threadIDs[i] == threadIDs[j]) { |
| 210 | threadIDs.clear(); |
| 211 | } |
| 212 | } |
| 213 | } |
| 214 | } |
| 215 | |
| 216 | /* re-map threadIDs if mapping is available */ |
| 217 | size_t ID = threadID; |
| 218 | if (threadID < threadIDs.size()) |
| 219 | ID = threadIDs[threadID]; |
| 220 | |
| 221 | /* find correct thread to affinitize to */ |
| 222 | cpu_set_t set; |
| 223 | CPU_ZERO(&set); |
| 224 | |
| 225 | if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0) |
| 226 | { |
| 227 | for (int i=0, j=0; i<CPU_SETSIZE; i++) |
| 228 | { |
| 229 | if (!CPU_ISSET(i,&set)) continue; |
| 230 | |
| 231 | if (j == ID) { |
| 232 | ID = i; |
| 233 | break; |