Skip to content
Closed
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
87 changes: 75 additions & 12 deletions cpp/src/arrow/util/cpu-info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#include <unistd.h>
#endif

#ifdef _WIN32
#include <windows.h>
#endif

#include <boost/algorithm/string.hpp>

#include <algorithm>
Expand Down Expand Up @@ -79,6 +83,45 @@ int64_t ParseCPUFlags(const string& values) {
return flags;
}

#ifdef _WIN32
bool RetrieveCacheSize(int64_t* cache_sizes) {
if (!cache_sizes) { return false; }
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = nullptr;
PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer_position = nullptr;
DWORD buffer_size = 0;
DWORD offset = 0;
typedef BOOL(WINAPI * GetLogicalProcessorInformationFuncPointer)(void*, void*);
GetLogicalProcessorInformationFuncPointer func_pointer =
(GetLogicalProcessorInformationFuncPointer)GetProcAddress(
GetModuleHandle("kernel32"), "GetLogicalProcessorInformation");

if (!func_pointer) { return false; }

// Get buffer size
if (func_pointer(buffer, &buffer_size) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return false;

buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(buffer_size);

if (!buffer || !func_pointer(buffer, &buffer_size)) { return false; }

buffer_position = buffer;
while (offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= buffer_size) {
if (RelationCache == buffer_position->Relationship) {
PCACHE_DESCRIPTOR cache = &buffer_position->Cache;
if (cache->Level >= 1 && cache->Level <= 3) {
cache_sizes[cache->Level - 1] += cache->Size;
}
}
offset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
buffer_position++;
}

if (buffer) { free(buffer); }
return true;
}
#endif

void CpuInfo::Init() {
std::lock_guard<std::mutex> cpuinfo_lock(cpuinfo_mutex);

Expand All @@ -93,6 +136,16 @@ void CpuInfo::Init() {

memset(&cache_sizes_, 0, sizeof(cache_sizes_));

#ifdef _WIN32
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
num_cores = system_info.dwNumberOfProcessors;

LARGE_INTEGER performance_frequency;
if (QueryPerformanceFrequency(&performance_frequency)) {
max_mhz = static_cast<float>(performance_frequency.QuadPart);
}
#else
// Read from /proc/cpuinfo
std::ifstream cpuinfo("/proc/cpuinfo", std::ios::in);
while (cpuinfo) {
Expand Down Expand Up @@ -120,6 +173,7 @@ void CpuInfo::Init() {
}
}
if (cpuinfo.is_open()) cpuinfo.close();
#endif

#ifdef __APPLE__
// On Mac OS X use sysctl() to get the cache sizes
Expand All @@ -131,22 +185,17 @@ void CpuInfo::Init() {
for (size_t i = 0; i < 3; ++i) {
cache_sizes_[i] = data[i];
}
#elif _WIN32
if (!RetrieveCacheSize(cache_sizes_)) { SetDefaultCacheSize(); }
#else
#ifndef _SC_LEVEL1_DCACHE_SIZE
// Provide reasonable default values if no info
cache_sizes_[0] = 32 * 1024; // Level 1: 32k
cache_sizes_[1] = 256 * 1024; // Level 2: 256k
cache_sizes_[2] = 3072 * 1024; // Level 3: 3M
#else
// Call sysconf to query for the cache sizes
cache_sizes_[0] = sysconf(_SC_LEVEL1_DCACHE_SIZE);
cache_sizes_[1] = sysconf(_SC_LEVEL2_CACHE_SIZE);
cache_sizes_[2] = sysconf(_SC_LEVEL3_CACHE_SIZE);
#endif
SetDefaultCacheSize();
#endif

if (max_mhz != 0) {
cycles_per_ms_ = static_cast<int64_t>(max_mhz) * 1000;
cycles_per_ms_ = static_cast<int64_t>(max_mhz);
#ifndef _WIN32
cycles_per_ms_ *= 1000;
#endif
} else {
cycles_per_ms_ = 1000000;
}
Expand Down Expand Up @@ -203,4 +252,18 @@ std::string CpuInfo::model_name() {
return model_name_;
}

void CpuInfo::SetDefaultCacheSize() {
#ifndef _SC_LEVEL1_DCACHE_SIZE
// Provide reasonable default values if no info
cache_sizes_[0] = 32 * 1024; // Level 1: 32k
cache_sizes_[1] = 256 * 1024; // Level 2: 256k
cache_sizes_[2] = 3072 * 1024; // Level 3: 3M
#else
// Call sysconf to query for the cache sizes
cache_sizes_[0] = sysconf(_SC_LEVEL1_DCACHE_SIZE);
cache_sizes_[1] = sysconf(_SC_LEVEL2_CACHE_SIZE);
cache_sizes_[2] = sysconf(_SC_LEVEL3_CACHE_SIZE);
#endif
}

} // namespace arrow
3 changes: 3 additions & 0 deletions cpp/src/arrow/util/cpu-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class ARROW_EXPORT CpuInfo {
static bool initialized() { return initialized_; }

private:
/// Inits CPU cache size variables with default values
static void SetDefaultCacheSize();

static bool initialized_;
static int64_t hardware_flags_;
static int64_t original_hardware_flags_;
Expand Down