| 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 | |