SystemStat suggestion


#1

Hi Jules,

It would be great for multithread programming to add a function to SystemStat to detect the number of logical cores (I assume that SystemStat::getNumCpus() returns the number of physical cores, right?), but processors like Intel i7 has 4 cores and each physical core has 2 logical cores so it can run 8 threads (if the CPU hyper-threading is enabled).
Just a suggestion.

Cheers,
Javi


#2

Yes indeed. (TBH, I’m not sure exactly whether that SystemStats call is consistent in returning the physical or logical number of processors across all platforms)


#3

I do it this way:

// ---------------------------------------------------------------------- 
TBool IsCPUHyperThreaded()
{
  UI32 rebx; 
  UI32 redx; 
  __asm 
  {
    push   eax
    push   ebx
    push   ecx
    push   edx
    mov    eax, 1
    _emit  0x0F
    _emit  0xA2 
    mov    redx, edx   
    mov    rebx, ebx   
    pop    edx         
    pop    ecx
    pop    ebx
    pop    eax
  } 

  return((redx & (1 << 28)) && (((rebx & 0x00FF0000) >> 16) > 1)); 
} 


// ---------------------------------------------------------------------- 
UI32 GetCPUNumLogicalProcessorsPerCore()
{ 
  UI32 rebx; 
  UI32 redx; 
  __asm 
  {
    push   eax
    push   ebx
    push   ecx
    push   edx
    mov    eax, 1
    _emit  0x0F
    _emit  0xA2 
    mov    redx, edx   
    mov    rebx, ebx   
    pop    edx         
    pop    ecx
    pop    ebx
    pop    eax
  } 

  UI32 num_processors = 1; 
  if(redx & (1 << 28)) 
  { 
    num_processors = (rebx & 0x00FF0000) >> 16; 
  } 

  return(num_processors); 
} 


// ---------------------------------------------------------------------- 
CPU_Vendor GetCPUVendor() 
{ 
  UI32 recx; 
  __asm 
  {
    push   eax
    push   ebx
    push   ecx
    push   edx
    mov    eax, 0
    _emit  0x0F
    _emit  0xA2 
    mov    recx, ecx 
    pop    edx         
    pop    ecx
    pop    ebx
    pop    eax
  } 

  CPU_Vendor vendor = CPU_VENDOR_UNKNOWN; 
  switch(recx) 
  { 
    case 0x6c65746e: 
      vendor = CPU_VENDOR_INTEL; 
      break; 
    case 0x444d4163: 
    case 0x21726574: 
      vendor = CPU_VENDOR_AMD; 
      break; 
    case 0x45495620: 
      vendor = CPU_VENDOR_VIA; 
      break; 
    case 0x53695320: 
      vendor = CPU_VENDOR_SIS; 
      break; 
    case 0x64616574: 
      vendor = CPU_VENDOR_CYRIX; 
      break; 
    case 0x43534e20: 
      vendor = CPU_VENDOR_NATIONAL_SEMICONDUCTOR; 
      break; 
    case 0x55504361: 
    case 0x3638784d: 
      vendor = CPU_VENDOR_TRANSMETA; 
      break; 
    case 0x6e657669: 
      vendor = CPU_VENDOR_NEXGEN; 
      break; 
    case 0x736c7561: 
      vendor = CPU_VENDOR_CENTAUR; 
      break; 
    case 0x65736952: 
      vendor = CPU_VENDOR_RISE; 
      break; 
    case 0x434d5520: 
      vendor = CPU_VENDOR_UMC; 
      break; 
  } 

  return(vendor); 
} 

IsCPUHyperThreaded() returns 1 only if Hyper Threading is available AND enabled.
GetCPUNumLogicalProcessorsPerCore() returns the number of logical processors in each physical core (if HT is not available always returns 1).
GetCPUVendor() is just to detect the vendor quickly.

Some references:

http://www.intel.com/content/dam/doc/application-note/processor-identification-cpuid-instruction-note.pdf
http://bochs.sourceforge.net/techspec/24161821.pdf
http://support.amd.com/us/Processor_TechDocs/25481.pdf


#4

Interesting, thanks!


#5

I forgot an important func:

UI32 GetCPUNumCores() 
{ 
  UI32 num_cores = 1; 
  __asm 
  { 
    push  eax 
    push  ebx 
    push  ecx 
    push  edx 
    xor   eax, eax  
    _emit 0x0F 
    _emit 0xA2 
    cmp   eax, 4 
    jl    _multicore_not_supported 
    mov   eax, 4 
    _emit 0x0F 
    _emit 0xA2 
    and   eax, 0xFC000000 
    shr   eax, 26 
    add   eax, 1 
    mov   num_cores, eax 
  _multicore_not_supported: 
    pop   edx 
    pop   ecx
    pop   ebx
    pop   eax
  } 

  return(num_cores); 
} 

This returns the number of cores per physical package, of course it returns 1 if the processor is single-core, and > 1 if it’s multi-core.

So with these functions is possible to detect whether the system has HT technology or multi-core architecture.


#6

Bumping this old thread because I’d like to suggest adding the opposite of what the original poster wanted here : a way to get the number of physical CPU cores from SystemStats instead of the number of logical cores.

I am not sure if SystemStats was even changed in the end as the original poster here wanted, but at least today on my 6 core i7 machine here (running Windows 7 64 bit), getNumCpus returns 12. (Because the CPU has hyperthreading…)

Maybe SystemStats should be changed so that getNumCpus keeps returning what it returns now, for compatibility with old code bases, and 3 new functions would be added : getNumPhysicalCPUCores, getNumLogicalCPUCores and hasHyperThreading? These should allow figuring out fairly well what the CPU actually has.