From 854013081f68cf2bce4461d6f1802ca262738cff Mon Sep 17 00:00:00 2001 From: Foereaper Date: Fri, 16 Aug 2024 20:17:41 +0200 Subject: [PATCH 1/5] Add cpu core and thread count functionality --- Source/Base/Base/Util/CPUInfo.cpp | 122 +++++++++++++----------------- Source/Base/Base/Util/CPUInfo.h | 3 + 2 files changed, 57 insertions(+), 68 deletions(-) diff --git a/Source/Base/Base/Util/CPUInfo.cpp b/Source/Base/Base/Util/CPUInfo.cpp index e343f7a1..705317da 100644 --- a/Source/Base/Base/Util/CPUInfo.cpp +++ b/Source/Base/Base/Util/CPUInfo.cpp @@ -4,14 +4,15 @@ #ifdef _WIN32 #include #include +#include #else #include +#include +//#include #endif using namespace std; -#define MAX_INTEL_TOP_LVL 4 - class CPUID { u32 regs[4]; @@ -66,6 +67,7 @@ void CPUInfo::Print(i32 detailLevel) NC_LOG_INFO("[CPUInfo]: Supports SSE4.2: {0}", features.isSSE42 ? "yes" : "no"); NC_LOG_INFO("[CPUInfo]: Supports AVX: {0}", features.isAVX ? "yes" : "no"); NC_LOG_INFO("[CPUInfo]: Supports AVX2: {0}", features.isAVX2 ? "yes" : "no"); + NC_LOG_INFO("[CPUInfo]: Supports AVX512F: {0}", features.isAVX512F ? "yes" : "no"); } } @@ -97,87 +99,71 @@ CPUInfo::CPUInfo() // Get AVX2 instructions availability CPUID cpuID7(7, 0); features.isAVX2 = cpuID7.EBX() & AVX2_POS; + features.isAVX512F = cpuID7.EBX() & AVX512F_POS; string upVId = _vendorId; for_each(upVId.begin(), upVId.end(), [](char& in) { in = ::toupper(in); }); + + // get physical and logical core information +#ifdef _WIN32 + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); - // Get num of cores - if (upVId.find("INTEL") != std::string::npos) + DWORD bufferSize = 0; + GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &bufferSize); + std::vector buffer(bufferSize); + GetLogicalProcessorInformationEx(RelationProcessorCore, reinterpret_cast(buffer.data()), &bufferSize); + + i32 num_physical_cores = 0; + auto* ptr = reinterpret_cast(buffer.data()); + while (bufferSize > 0) { - if (HFS >= 11) - { - for (i32 lvl = 0; lvl < MAX_INTEL_TOP_LVL; ++lvl) - { - CPUID cpuID4(0x0B, lvl); - u32 currLevel = (LVL_TYPE & cpuID4.ECX()) >> 8; - - switch (currLevel) - { - case 0x01: _numThreadsPerCore = LVL_CORES & cpuID4.EBX(); break; - case 0x02: _numThreads = LVL_CORES & cpuID4.EBX(); break; - default: break; - } - } - _numCores = _numThreads / _numThreadsPerCore; - } - else + if (ptr->Relationship == RelationProcessorCore) { - if (HFS >= 1) - { - _numThreads = (cpuID1.EBX() >> 16) & 0xFF; - if (HFS >= 4) - { - _numCores = 1 + (CPUID(4, 0).EAX() >> 26) & 0x3F; - } - } - if (features.isHTT) - { - if (!(_numCores > 1)) - { - _numCores = 1; - _numThreads = (_numThreads >= 2 ? _numThreads : 2); - } - } - else - { - _numCores = _numThreads = 1; - } + ++num_physical_cores; } + bufferSize -= ptr->Size; + ptr = reinterpret_cast(reinterpret_cast(ptr) + ptr->Size); } - else if (upVId.find("AMD") != std::string::npos) + + // set physical cores + _numCores = num_physical_cores; + + // set logical cores + _numThreads = static_cast(sysinfo.dwNumberOfProcessors); +#else + // init hwloc topology + //hwloc_topology_t topology; + //hwloc_topology_init(&topology); + //hwloc_topology_load(topology); + + // get the number of physical cores + //i32 num_physical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); + + // get the number of logical cores + //i32 num_logical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); + + // deinit hwloc + //hwloc_topology_destroy(topology); + + // set physical cores + _numCores = sysconf(_SC_NPROCESSORS_ONLN); //num_physical_cores; + // set logical cores + _numThreads = sysconf(_SC_NPROCESSORS_CONF); //num_logical_cores; +#endif + + // if set the amount of threads per core + if (_numThreads > _numCores) { - if (HFS >= 1) - { - _numThreads = (cpuID1.EBX() >> 16) & 0xFF; - if (CPUID(0x80000000, 0).EAX() >= 8) - { - _numCores = 1 + (CPUID(0x80000008, 0).ECX() & 0xFF); - } - } - if (features.isHTT) - { - if (!(_numCores > 1)) - { - _numCores = 1; - _numThreads = (_numThreads >= 2 ? _numThreads : 2); - } - else - { - _numThreadsPerCore = 2; - _numCores = _numThreads / _numThreadsPerCore; - } - } - else - { - _numCores = _numThreads = 1; - } + _numThreadsPerCore = _numThreads / _numCores; + features.isHTT = 1; } else { - //NC_LOG_CRITICAL("Unexpected vendor id ({0})", upVId.c_str()); + _numThreadsPerCore = 1; } // Get processor brand string diff --git a/Source/Base/Base/Util/CPUInfo.h b/Source/Base/Base/Util/CPUInfo.h index 78a74c24..b94fcaad 100644 --- a/Source/Base/Base/Util/CPUInfo.h +++ b/Source/Base/Base/Util/CPUInfo.h @@ -22,6 +22,7 @@ class CPUInfo bool IsSSE42() const { return features.isSSE42; } bool IsAVX() const { return features.isAVX; } bool IsAVX2() const { return features.isAVX2; } + bool isAVX512F() const { return features.isAVX512F; } bool IsHyperThreaded() const { return features.isHTT; } void Print(i32 detailLevel); @@ -41,6 +42,7 @@ class CPUInfo static const u32 SSE42_POS = 0x00100000; static const u32 AVX_POS = 0x10000000; static const u32 AVX2_POS = 0x00000020; + static const u32 AVX512F_POS = 0x00008000; static const u32 LVL_NUM = 0x000000FF; static const u32 LVL_TYPE = 0x0000FF00; static const u32 LVL_CORES = 0x0000FFFF; @@ -64,6 +66,7 @@ class CPUInfo u8 isSSE42 : 1; u8 isAVX : 1; u8 isAVX2 : 1; + u8 isAVX512F : 1; }; Features features; From 5ff558e5222de5e948054d8bc86aa6797863be5f Mon Sep 17 00:00:00 2001 From: Foereaper Date: Fri, 16 Aug 2024 20:33:20 +0200 Subject: [PATCH 2/5] Add debug output for physical and logical cores --- Source/Base/Base/Util/CPUInfo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Base/Base/Util/CPUInfo.cpp b/Source/Base/Base/Util/CPUInfo.cpp index 705317da..f6f40445 100644 --- a/Source/Base/Base/Util/CPUInfo.cpp +++ b/Source/Base/Base/Util/CPUInfo.cpp @@ -52,6 +52,8 @@ CPUInfo& CPUInfo::Get() void CPUInfo::Print(i32 detailLevel) { + NC_LOG_INFO("[CPUInfo]: Physical cores: {0}", _numCores); + NC_LOG_INFO("[CPUInfo]: Logical cores: {0}", _numThreads); if (detailLevel > 0) { NC_LOG_INFO("[CPUInfo]: {0}", _prettyName); From 785d6d65081848029332b67d1ae0f5661a9ab844 Mon Sep 17 00:00:00 2001 From: Foereaper Date: Fri, 16 Aug 2024 20:56:12 +0200 Subject: [PATCH 3/5] Add hwloc to determine cpu core count --- .github/workflows/linux-build.yml | 2 +- Dependencies/Dependencies.lua | 3 ++- Dependencies/hwloc/hwloc.lua | 8 ++++++++ Source/Base/Base.lua | 2 +- Source/Base/Base/Util/CPUInfo.cpp | 19 +++++++++---------- 5 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 Dependencies/hwloc/hwloc.lua diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 9524d9c7..01d100b9 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -23,7 +23,7 @@ jobs: # - name: Install dependencies # run: | -# sudo apt-get update && sudo apt-get install -yq clang libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libvulkan-dev +# sudo apt-get update && sudo apt-get install -yq clang libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libvulkan-dev hwloc libhwloc-dev # sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-14 100 # - name: Install Vulkan SDK diff --git a/Dependencies/Dependencies.lua b/Dependencies/Dependencies.lua index eec88963..30b71de0 100644 --- a/Dependencies/Dependencies.lua +++ b/Dependencies/Dependencies.lua @@ -23,7 +23,8 @@ local dependencies = "utfcpp/utfcpp.lua", "luau/luau.lua", "quill/quill.lua", - "asio/asio.lua" + "asio/asio.lua", + "hwloc/hwloc.lua" } for k,v in pairs(dependencies) do diff --git a/Dependencies/hwloc/hwloc.lua b/Dependencies/hwloc/hwloc.lua new file mode 100644 index 00000000..7fc2a476 --- /dev/null +++ b/Dependencies/hwloc/hwloc.lua @@ -0,0 +1,8 @@ +local dep = Solution.Util.CreateDepTable("hwloc", {}) + +Solution.Util.CreateDep(dep.Name, dep.Dependencies, function() + if os.target() == "linux" then + Solution.Util.SetIncludes({ "/usr/include/hwloc" }) + Solution.Util.SetLinks({ "hwloc" }) + end +end) \ No newline at end of file diff --git a/Source/Base/Base.lua b/Source/Base/Base.lua index 03bc86d0..5f49825a 100644 --- a/Source/Base/Base.lua +++ b/Source/Base/Base.lua @@ -1,4 +1,4 @@ -local mod = Solution.Util.CreateModuleTable("Base", { "glm", "robinhood", "json", "refl-cpp", "quill" }) +local mod = Solution.Util.CreateModuleTable("Base", { "glm", "robinhood", "json", "refl-cpp", "quill", "hwloc" }) Solution.Util.CreateStaticLib(mod.Name, Solution.Projects.Current.BinDir, mod.Dependencies, function() local defines = { "_CRT_SECURE_NO_WARNINGS", "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS", "_SILENCE_ALL_MS_EXT_DEPRECATION_WARNINGS" } diff --git a/Source/Base/Base/Util/CPUInfo.cpp b/Source/Base/Base/Util/CPUInfo.cpp index f6f40445..41cc00d7 100644 --- a/Source/Base/Base/Util/CPUInfo.cpp +++ b/Source/Base/Base/Util/CPUInfo.cpp @@ -7,8 +7,7 @@ #include #else #include -#include -//#include +#include #endif using namespace std; @@ -138,23 +137,23 @@ CPUInfo::CPUInfo() _numThreads = static_cast(sysinfo.dwNumberOfProcessors); #else // init hwloc topology - //hwloc_topology_t topology; - //hwloc_topology_init(&topology); - //hwloc_topology_load(topology); + hwloc_topology_t topology; + hwloc_topology_init(&topology); + hwloc_topology_load(topology); // get the number of physical cores - //i32 num_physical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); + i32 num_physical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); // get the number of logical cores - //i32 num_logical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); + i32 num_logical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); // deinit hwloc - //hwloc_topology_destroy(topology); + hwloc_topology_destroy(topology); // set physical cores - _numCores = sysconf(_SC_NPROCESSORS_ONLN); //num_physical_cores; + _numCores = num_physical_cores; // set logical cores - _numThreads = sysconf(_SC_NPROCESSORS_CONF); //num_logical_cores; + _numThreads = num_logical_cores; #endif // if set the amount of threads per core From e13b908e836a4078918da04c8d08d94e11550da3 Mon Sep 17 00:00:00 2001 From: Foereaper Date: Fri, 16 Aug 2024 21:05:05 +0200 Subject: [PATCH 4/5] Switch to camel case --- Source/Base/Base/Util/CPUInfo.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Source/Base/Base/Util/CPUInfo.cpp b/Source/Base/Base/Util/CPUInfo.cpp index 41cc00d7..0a3e1f19 100644 --- a/Source/Base/Base/Util/CPUInfo.cpp +++ b/Source/Base/Base/Util/CPUInfo.cpp @@ -118,20 +118,20 @@ CPUInfo::CPUInfo() std::vector buffer(bufferSize); GetLogicalProcessorInformationEx(RelationProcessorCore, reinterpret_cast(buffer.data()), &bufferSize); - i32 num_physical_cores = 0; + i32 numPhysicalCores = 0; auto* ptr = reinterpret_cast(buffer.data()); while (bufferSize > 0) { if (ptr->Relationship == RelationProcessorCore) { - ++num_physical_cores; + ++numPhysicalCores; } bufferSize -= ptr->Size; ptr = reinterpret_cast(reinterpret_cast(ptr) + ptr->Size); } // set physical cores - _numCores = num_physical_cores; + _numCores = numPhysicalCores; // set logical cores _numThreads = static_cast(sysinfo.dwNumberOfProcessors); @@ -142,18 +142,18 @@ CPUInfo::CPUInfo() hwloc_topology_load(topology); // get the number of physical cores - i32 num_physical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); + i32 numPhysicalCores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE); // get the number of logical cores - i32 num_logical_cores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); + i32 numLogicalCores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU); // deinit hwloc hwloc_topology_destroy(topology); // set physical cores - _numCores = num_physical_cores; + _numCores = numPhysicalCores; // set logical cores - _numThreads = num_logical_cores; + _numThreads = numLogicalCores; #endif // if set the amount of threads per core From 4f5e5e1a5e11031e6625f51f5561774fcf5b4bec Mon Sep 17 00:00:00 2001 From: Foereaper Date: Fri, 16 Aug 2024 21:07:15 +0200 Subject: [PATCH 5/5] Remove debug output --- Source/Base/Base/Util/CPUInfo.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/Base/Base/Util/CPUInfo.cpp b/Source/Base/Base/Util/CPUInfo.cpp index 0a3e1f19..9e6ac10c 100644 --- a/Source/Base/Base/Util/CPUInfo.cpp +++ b/Source/Base/Base/Util/CPUInfo.cpp @@ -51,8 +51,6 @@ CPUInfo& CPUInfo::Get() void CPUInfo::Print(i32 detailLevel) { - NC_LOG_INFO("[CPUInfo]: Physical cores: {0}", _numCores); - NC_LOG_INFO("[CPUInfo]: Logical cores: {0}", _numThreads); if (detailLevel > 0) { NC_LOG_INFO("[CPUInfo]: {0}", _prettyName);