Skip to content

Commit 1e3cb8e

Browse files
committed
cpu_count template
1 parent 6a78af9 commit 1e3cb8e

File tree

5 files changed

+101
-16
lines changed

5 files changed

+101
-16
lines changed

benchmark/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ add_library(partition OBJECT partition.f90)
2929
3030
add_library(cli OBJECT cli.f90)
3131
32-
add_executable(runner frontend.f90 cpu.cpp)
32+
add_executable(runner frontend.f90 cpu_count.cpp)
33+
target_include_directories(runner PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
3334
target_link_libraries(runner PRIVATE partition cli)
3435
if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel")
3536
set_property(TARGET runner PROPERTY LINKER_LANGUAGE Fortran)

benchmark/cpu.cpp renamed to benchmark/cpu_count.cpp

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// MacOS (g++, clang++, icpc)
77
// Linux (g++, clang++, icpx)
88

9+
// Compiler OS-detection macros
10+
// https://sourceforge.net/p/predef/wiki/OperatingSystems/
11+
912
#include <vector>
1013
#include <cassert>
1114
#include <bitset>
@@ -19,19 +22,53 @@
1922
#include <windows.h>
2023
#elif defined (__APPLE__)
2124
#include <sys/sysctl.h>
22-
#else
25+
#elif __has_include(<unistd.h>)
2326
#include <unistd.h>
2427
#endif
2528

26-
extern "C" unsigned int cpu_count();
29+
unsigned int CPUCountWindows();
30+
unsigned int ParseSysCtl();
31+
unsigned int RetrieveInformationFromCpuInfoFile();
32+
unsigned int QueryProcessorBySysconf();
33+
unsigned int QueryThreads();
2734

2835
std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
2936
size_t& CurrentPositionInFile, size_t init = 0);
3037

38+
#ifdef __cplusplus
39+
extern "C" {
40+
#endif
3141

3242
unsigned int cpu_count(){
3343

3444
unsigned int NumberOfPhysicalCPU = 0;
45+
46+
#if defined (_WIN32)
47+
NumberOfPhysicalCPU = CPUCountWindows();
48+
#elif defined (__APPLE__)
49+
NumberOfPhysicalCPU = ParseSysCtl();
50+
#elif defined (__unix__)
51+
NumberOfPhysicalCPU = RetrieveInformationFromCpuInfoFile();
52+
#endif
53+
54+
if (NumberOfPhysicalCPU == 0)
55+
NumberOfPhysicalCPU = QueryProcessorBySysconf();
56+
57+
if (NumberOfPhysicalCPU == 0)
58+
NumberOfPhysicalCPU = QueryThreads();
59+
60+
return NumberOfPhysicalCPU;
61+
62+
}
63+
64+
#ifdef __cplusplus
65+
}
66+
#endif
67+
68+
69+
unsigned int CPUCountWindows(){
70+
71+
unsigned int NumberOfPhysicalCPU = 0;
3572
unsigned int NumberOfLogicalCPU = 0;
3673

3774
#ifdef _WIN32
@@ -51,10 +88,12 @@ unsigned int cpu_count(){
5188
DWORD Length = 0;
5289
DWORD rc = pGetLogicalProcessorInformation(nullptr, &Length);
5390
assert(rc == 0);
91+
(void)rc; // Silence unused variable warning
5492
assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
5593
ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
5694
rc = pGetLogicalProcessorInformation(&ProcInfo[0], &Length);
5795
assert(rc != 0);
96+
(void)rc; // Silence unused variable warning
5897
}
5998

6099
typedef std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>::iterator
@@ -75,8 +114,17 @@ unsigned int cpu_count(){
75114
NumberOfLogicalCPU += (unsigned int)count;
76115
}
77116

78-
#elif defined(__linux)
117+
#endif
118+
119+
return NumberOfPhysicalCPU;
120+
121+
}
122+
79123

124+
unsigned int RetrieveInformationFromCpuInfoFile(){
125+
126+
unsigned int NumberOfLogicalCPU = 0;
127+
unsigned int NumberOfPhysicalCPU = 0;
80128
std::string buffer;
81129

82130
FILE* fd = fopen("/proc/cpuinfo", "r");
@@ -109,9 +157,8 @@ unsigned int cpu_count(){
109157
}
110158

111159
uint64_t NumberOfSockets = PhysicalIDs.size();
112-
NumberOfSockets = std::max(NumberOfSockets, (uint64_t)1);
113160
// Physical ids returned by Linux don't distinguish cores.
114-
// We want to record the total number of cores in this->NumberOfPhysicalCPU
161+
// We want to record the total number of cores in NumberOfPhysicalCPU
115162
// (checking only the first proc)
116163
std::string Cores = ExtractValueFromCpuInfoFile(buffer, "cpu cores", CurrentPositionInFile);
117164
if (Cores.empty()) {
@@ -122,7 +169,15 @@ unsigned int cpu_count(){
122169
NumberOfCoresPerSocket = std::max(NumberOfCoresPerSocket, 1u);
123170
NumberOfPhysicalCPU = NumberOfCoresPerSocket * (unsigned int)NumberOfSockets;
124171

125-
#elif defined(__APPLE__)
172+
return NumberOfPhysicalCPU;
173+
174+
}
175+
176+
unsigned int ParseSysCtl(){
177+
178+
unsigned int NumberOfPhysicalCPU = 0;
179+
180+
#ifdef __APPLE__
126181

127182
int N;
128183
size_t size = sizeof(N);
@@ -136,20 +191,39 @@ unsigned int cpu_count(){
136191
NumberOfPhysicalCPU = N;
137192
}
138193

139-
#elif defined(_SC_NPROCESSORS_ONLN)
194+
#endif
195+
196+
return NumberOfPhysicalCPU;
140197

141-
long N = sysconf(_SC_NPROCESSORS_ONLN);
142-
if (N > 0)
143-
NumberOfPhysicalCPU = static_cast<unsigned int>(N);
198+
}
199+
200+
unsigned int QueryProcessorBySysconf(){
201+
202+
unsigned int NumberOfPhysicalCPU = 0;
203+
204+
#if defined(_SC_NPROCESSORS_ONLN)
205+
206+
long c = sysconf(_SC_NPROCESSORS_ONLN);
207+
if (c > 0)
208+
NumberOfPhysicalCPU = static_cast<unsigned int>(c);
144209

145-
#else
146-
NumberOfPhysicalCPU = std::thread::hardware_concurrency();
147210
#endif
148211

149-
return NumberOfPhysicalCPU;
212+
return NumberOfPhysicalCPU;
150213

151214
}
152215

216+
unsigned int QueryThreads(){
217+
// fallback, doesn't consider hyperthreading
218+
219+
unsigned int NumberOfLogicalCPU = std::thread::hardware_concurrency();
220+
unsigned int NumberOfPhysicalCPU = NumberOfLogicalCPU;
221+
222+
return NumberOfPhysicalCPU;
223+
224+
}
225+
226+
153227
/** Extract a value from the CPUInfo file */
154228
std::string ExtractValueFromCpuInfoFile(std::string buffer, const char* word,
155229
size_t & CurrentPositionInFile, size_t init)

benchmark/cpu_count.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifdef __cplusplus
2+
extern "C" {
3+
#endif
4+
5+
unsigned int cpu_count();
6+
7+
#ifdef __cplusplus
8+
}
9+
#endif

fpm.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "h5fortran-mpi"
22
description = "Lightweight object-oriented HDF5 MPI parallel interface"
33
categories = "io"
4-
version = "1.0.1"
4+
version = "2.0.0"
55

66
[build]
77
auto-tests = false

test/mpi/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ endfunction(mpi_test)
3232
# --- test files
3333

3434
add_executable(test_runner runner.f90
35-
${PROJECT_SOURCE_DIR}/benchmark/cpu.cpp
35+
${PROJECT_SOURCE_DIR}/benchmark/cpu_count.cpp
3636
${PROJECT_SOURCE_DIR}/benchmark/partition.f90
3737
${PROJECT_SOURCE_DIR}/benchmark/cli.f90
3838
)
39+
target_include_directories(test_runner PRIVATE ${PROJECT_SOURCE_DIR}/benchmark)
3940
# not linked as libraries in case benchmarks aren't built
4041
if(CMAKE_Fortran_COMPILER_ID MATCHES "^Intel")
4142
set_property(TARGET test_runner PROPERTY LINKER_LANGUAGE Fortran)

0 commit comments

Comments
 (0)