1 | #include <Common/getNumberOfPhysicalCPUCores.h> |
2 | #include <thread> |
3 | |
4 | #include <Common/config.h> |
5 | #if USE_CPUID |
6 | # include <libcpuid/libcpuid.h> |
7 | # include <Common/Exception.h> |
8 | namespace DB { namespace ErrorCodes { extern const int CPUID_ERROR; }} |
9 | #elif USE_CPUINFO |
10 | # include <cpuinfo.h> |
11 | #endif |
12 | |
13 | |
14 | |
15 | unsigned getNumberOfPhysicalCPUCores() |
16 | { |
17 | #if USE_CPUID |
18 | cpu_raw_data_t raw_data; |
19 | cpu_id_t data; |
20 | |
21 | /// On Xen VMs, libcpuid returns wrong info (zero number of cores). Fallback to alternative method. |
22 | /// Also, libcpuid does not support some CPUs like AMD Hygon C86 7151. |
23 | if (0 != cpuid_get_raw_data(&raw_data) || 0 != cpu_identify(&raw_data, &data) || data.num_logical_cpus == 0) |
24 | return std::thread::hardware_concurrency(); |
25 | |
26 | unsigned res = data.num_cores * data.total_logical_cpus / data.num_logical_cpus; |
27 | |
28 | /// Also, libcpuid gives strange result on Google Compute Engine VMs. |
29 | /// Example: |
30 | /// num_cores = 12, /// number of physical cores on current CPU socket |
31 | /// total_logical_cpus = 1, /// total number of logical cores on all sockets |
32 | /// num_logical_cpus = 24. /// number of logical cores on current CPU socket |
33 | /// It means two-way hyper-threading (24 / 12), but contradictory, 'total_logical_cpus' == 1. |
34 | |
35 | if (res != 0) |
36 | return res; |
37 | |
38 | #elif USE_CPUINFO |
39 | uint32_t cores = 0; |
40 | if (cpuinfo_initialize()) |
41 | cores = cpuinfo_get_cores_count(); |
42 | |
43 | if (cores) |
44 | return cores; |
45 | #endif |
46 | |
47 | /// As a fallback (also for non-x86 architectures) assume there are no hyper-threading on the system. |
48 | /// (Actually, only Aarch64 is supported). |
49 | return std::thread::hardware_concurrency(); |
50 | } |
51 | |