llvm.org GIT mirror llvm / 26cb3d9
Add interface to compute number of physical cores on host system Summary: For now I have only added support for x86_64 Linux, but other systems can be added incrementally. This is to be used for setting the default parallelism for ThinLTO backends (instead of thread::hardware_concurrency which includes hyperthreading and is too aggressive). I'll send this as a follow-on patch, and it will fall back to hardware_concurrency when the new getHostNumPhysicalCores returns -1 (when not supported for a given host system). I also added an interface to MemoryBuffer to force reading a file as a stream - this is required for /proc/cpuinfo which is a special file that looks like a normal file but appears to have 0 size. The existing readers of this file in Host.cpp are reading the first 1024 or so bytes from it, because the necessary info is near the top. But for the new functionality we need to be able to read the entire file. I can go back and change the other readers to use the new getFileAsStream as a follow-on patch since it seems much more robust. Added a unittest. Reviewers: mehdi_amini Subscribers: beanz, mgorny, llvm-commits, modocache Differential Revision: https://reviews.llvm.org/D25564 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284138 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
6 changed file(s) with 128 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
6969 ///
7070 /// \return - True on success.
7171 bool getHostCPUFeatures(StringMap &Features);
72
73 /// Get the number of physical cores (as opposed to logical cores returned
74 /// from thread::hardware_concurrency(), which includes hyperthreads).
75 /// Returns -1 if unknown for the current host system.
76 int getHostNumPhysicalCores();
7277 }
7378 }
7479
6868 static ErrorOr>
6969 getFile(const Twine &Filename, int64_t FileSize = -1,
7070 bool RequiresNullTerminator = true, bool IsVolatileSize = false);
71
72 /// Read all of the specified file into a MemoryBuffer as a stream
73 /// (i.e. until EOF reached). This is useful for special files that
74 /// look like a regular file but have 0 size (e.g. /proc/cpuinfo on Linux).
75 static ErrorOr>
76 getFileAsStream(const Twine &Filename);
7177
7278 /// Given an already-open file descriptor, map some slice of it into a
7379 /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize.
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "llvm/Support/Host.h"
14 #include "llvm/ADT/SmallSet.h"
1415 #include "llvm/ADT/SmallVector.h"
1516 #include "llvm/ADT/StringRef.h"
1617 #include "llvm/ADT/StringSwitch.h"
1819 #include "llvm/Config/config.h"
1920 #include "llvm/Support/Debug.h"
2021 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/MemoryBuffer.h"
2123 #include "llvm/Support/raw_ostream.h"
24 #include
2225 #include
23 #include
2426
2527 // Include the platform-specific parts of this class.
2628 #ifdef LLVM_ON_UNIX
11871189 StringRef sys::getHostCPUName() { return "generic"; }
11881190 #endif
11891191
1192 #if defined(__linux__) && defined(__x86_64__)
1193 // On Linux, the number of physical cores can be computed from /proc/cpuinfo,
1194 // using the number of unique physical/core id pairs. The following
1195 // implementation reads the /proc/cpuinfo format on an x86_64 system.
1196 int computeHostNumPhysicalCores() {
1197 // Read /proc/cpuinfo as a stream (until EOF reached). It cannot be
1198 // mmapped because it appears to have 0 size.
1199 llvm::ErrorOr> Text =
1200 llvm::MemoryBuffer::getFileAsStream("/proc/cpuinfo");
1201 if (std::error_code EC = Text.getError()) {
1202 llvm::errs() << "Can't read "
1203 << "/proc/cpuinfo: " << EC.message() << "\n";
1204 }
1205 SmallVector strs;
1206 (*Text)->getBuffer().split(strs, "\n", /*MaxSplit=*/-1,
1207 /*KeepEmpty=*/false);
1208 int CurPhysicalId = -1;
1209 int CurCoreId = -1;
1210 SmallSet, 32> UniqueItems;
1211 for (auto &Line : strs) {
1212 Line = Line.trim();
1213 if (!Line.startswith("physical id") && !Line.startswith("core id"))
1214 continue;
1215 std::pair Data = Line.split(':');
1216 auto Name = Data.first.trim();
1217 auto Val = Data.second.trim();
1218 if (Name == "physical id") {
1219 assert(CurPhysicalId == -1 &&
1220 "Expected a core id before seeing another physical id");
1221 Val.getAsInteger(10, CurPhysicalId);
1222 }
1223 if (Name == "core id") {
1224 assert(CurCoreId == -1 &&
1225 "Expected a physical id before seeing another core id");
1226 Val.getAsInteger(10, CurCoreId);
1227 }
1228 if (CurPhysicalId != -1 && CurCoreId != -1) {
1229 UniqueItems.insert(std::make_pair(CurPhysicalId, CurCoreId));
1230 CurPhysicalId = -1;
1231 CurCoreId = -1;
1232 }
1233 }
1234 return UniqueItems.size();
1235 }
1236 #else
1237 // On other systems, return -1 to indicate unknown.
1238 int computeHostNumPhysicalCores() { return -1; }
1239 #endif
1240
1241 int sys::getHostNumPhysicalCores() {
1242 static int NumCores = computeHostNumPhysicalCores();
1243 return NumCores;
1244 }
1245
11901246 #if defined(__i386__) || defined(_M_IX86) || \
11911247 defined(__x86_64__) || defined(_M_X64)
11921248 bool sys::getHostCPUFeatures(StringMap &Features) {
437437 return getMemoryBufferForStream(0, "");
438438 }
439439
440 ErrorOr>
441 MemoryBuffer::getFileAsStream(const Twine &Filename) {
442 int FD;
443 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
444 if (EC)
445 return EC;
446 ErrorOr> Ret =
447 getMemoryBufferForStream(FD, Filename);
448 close(FD);
449 return Ret;
450 }
451
440452 MemoryBufferRef MemoryBuffer::getMemBufferRef() const {
441453 StringRef Data = getBuffer();
442454 StringRef Identifier = getBufferIdentifier();
1818 ErrorTest.cpp
1919 ErrorOrTest.cpp
2020 FileOutputBufferTest.cpp
21 Host.cpp
2122 LEB128Test.cpp
2223 LineIteratorTest.cpp
2324 LockFileManagerTest.cpp
0 //========- unittests/Support/Host.cpp - Host.cpp tests --------------========//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/Support/Host.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/Triple.h"
12
13 #include "gtest/gtest.h"
14
15 using namespace llvm;
16
17 class HostTest : public testing::Test {
18 Triple Host;
19 SmallVector, 4> SupportedArchAndOSs;
20
21 protected:
22 bool isSupportedArchAndOS() {
23 if (is_contained(SupportedArchAndOSs, std::make_pair(Host.getArch(), Host.getOS())))
24 return true;
25
26 return false;
27 }
28
29 HostTest() {
30 Host.setTriple(Triple::normalize(sys::getProcessTriple()));
31
32 // Initially this is only testing detection of the number of
33 // physical cores, which is currently only supported for
34 // x86_64 Linux.
35 SupportedArchAndOSs.push_back(std::make_pair(Triple::x86_64, Triple::Linux));
36 }
37 };
38
39 TEST_F(HostTest, NumPhysicalCores) {
40 int Num = sys::getHostNumPhysicalCores();
41
42 if (isSupportedArchAndOS())
43 ASSERT_GT(Num, 0);
44 else
45 ASSERT_EQ(Num, -1);
46 }