Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add physical and logical core count support #39

Merged
merged 5 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linux-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion Dependencies/Dependencies.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions Dependencies/hwloc/hwloc.lua
Original file line number Diff line number Diff line change
@@ -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)
2 changes: 1 addition & 1 deletion Source/Base/Base.lua
Original file line number Diff line number Diff line change
@@ -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" }
Expand Down
121 changes: 53 additions & 68 deletions Source/Base/Base/Util/CPUInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#ifdef _WIN32
#include <limits.h>
#include <intrin.h>
#include <windows.h>
#else
#include <stdint.h>
#include <hwloc.h>
#endif

using namespace std;

#define MAX_INTEL_TOP_LVL 4

class CPUID
{
u32 regs[4];
Expand Down Expand Up @@ -66,6 +66,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");
}
}

Expand Down Expand Up @@ -97,87 +98,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<uint8_t> buffer(bufferSize);
GetLogicalProcessorInformationEx(RelationProcessorCore, reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(buffer.data()), &bufferSize);

i32 numPhysicalCores = 0;
auto* ptr = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(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;
}
++numPhysicalCores;
}
bufferSize -= ptr->Size;
ptr = reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*>(reinterpret_cast<uint8_t*>(ptr) + ptr->Size);
}
else if (upVId.find("AMD") != std::string::npos)

// set physical cores
_numCores = numPhysicalCores;

// set logical cores
_numThreads = static_cast<i32>(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 numPhysicalCores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_CORE);

// get the number of logical cores
i32 numLogicalCores = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PU);

// deinit hwloc
hwloc_topology_destroy(topology);

// set physical cores
_numCores = numPhysicalCores;
// set logical cores
_numThreads = numLogicalCores;
#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
Expand Down
3 changes: 3 additions & 0 deletions Source/Base/Base/Util/CPUInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -64,6 +66,7 @@ class CPUInfo
u8 isSSE42 : 1;
u8 isAVX : 1;
u8 isAVX2 : 1;
u8 isAVX512F : 1;
};

Features features;
Expand Down