超線程是英特爾實施的simultaneous multithreading (SMT)。目前的AMD處理器沒有實現SMT(Bulldozer微架構家族有其他的稱之爲基於集羣的多線程的東西,但Zen微架構假設有SMT)。 OpenMP沒有內置的支持來檢測SMT。
如果你想要一個通用的函數來檢測超線程,你需要支持不同代的處理器,並確保處理器是Intel處理器而不是AMD處理器。最好爲此使用一個庫。
但是,您可以使用OpenMP創建功能,該功能適用於許多現代Intel處理器,如我所述的here。
以下代碼將計算現代英特爾處理器上的物理內核數(它已在我嘗試使用的每個英特爾處理器上工作)。你必須綁定線程才能使其工作。使用GCC,您可以使用 export OMP_PROC_BIND=true
,否則您可以使用bind with code(這是我所做的)。
請注意,我不確定這種方法在VirtualBox中是否可靠。將VirtualBox放在一個4核心/ 8邏輯處理器CPU上,並將Windows作爲主機和Linux作爲猜測將虛擬機的核心數量設置爲4,則此代碼報告2個核心,而/ proc/cpuinfo顯示其中兩個核心實際上是邏輯處理器。
#include <stdio.h>
//cpuid function defined in instrset_detect.cpp by Agner Fog (2014 GNU General Public License)
//http://www.agner.org/optimize/vectorclass.zip
// Define interface to cpuid instruction.
// input: eax = functionnumber, ecx = 0
// output: eax = output[0], ebx = output[1], ecx = output[2], edx = output[3]
static inline void cpuid (int output[4], int functionnumber) {
#if defined (_MSC_VER) || defined (__INTEL_COMPILER) // Microsoft or Intel compiler, intrin.h included
__cpuidex(output, functionnumber, 0); // intrinsic function for CPUID
#elif defined(__GNUC__) || defined(__clang__) // use inline assembly, Gnu/AT&T syntax
int a, b, c, d;
__asm("cpuid" : "=a"(a),"=b"(b),"=c"(c),"=d"(d) : "a"(functionnumber),"c"(0) :);
output[0] = a;
output[1] = b;
output[2] = c;
output[3] = d;
#else // unknown platform. try inline assembly with masm/intel syntax
__asm {
mov eax, functionnumber
xor ecx, ecx
cpuid;
mov esi, output
mov [esi], eax
mov [esi+4], ebx
mov [esi+8], ecx
mov [esi+12], edx
}
#endif
}
int getNumCores(void) {
//Assuming an Intel processor with CPUID leaf 11
int cores = 0;
#pragma omp parallel reduction(+:cores)
{
int regs[4];
cpuid(regs,11);
if(!(regs[3]&1)) cores++;
}
return cores;
}
int main(void) {
printf("cores %d\n", getNumCores());
}
不,沒有簡單的方法來做到這一點全自動。但有http://stackoverflow.com/q/2901694/620382 +'omp_set_num_threads'。如果可行,我建議再次手動控制每個系統上的線程配置。 – Zulan
這個問題爲什麼downvoted?! – cnst