Linux, Anzahl der CPU-Kerne

Moien

Wie kann man zur Laufzeit bestimmen wieviele Kerne ein System hat?

Danke

Hallo

Wie kann man zur Laufzeit bestimmen wieviele Kerne ein System hat?

mit

 cat /proc/cpuinfo | perl -ne 'print "$1 " if /proc.\*?:\s\*(\d+)/'

oder mit sensors, wenn das installiert ist.

Ich vermute mal, Du willst das aus einem
C-Programm heraus machen(?).

Grüße

CMБ

Moien

Ich vermute mal, Du willst das aus einem
C-Programm heraus machen(?).

Ja. Mit Script und über eine Console ist zwar ganz nett aber das muss auch so gehen.

cu

Hallo

Ich vermute mal, Du willst das aus einem
C-Programm heraus machen(?).

Ja. Mit Script und über eine Console ist zwar ganz nett aber
das muss auch so gehen.

Wie denn? In C? In C++?

Grüße

CMБ

Moien

Ich vermute mal, Du willst das aus einem
C-Programm heraus machen(?).

Ja. Mit Script und über eine Console ist zwar ganz nett aber
das muss auch so gehen.

Wie denn? In C? In C++?

Das wär mir sogar relativ wurscht. Das Projekt benutzt derzeit eh beides. Ich muss nur wissen wieviele pthreads man sinnvollerweise bauen kann. Das Ding scaliert sehr gut und läuft auch bei 8 Kernen noch anständig (730% Steigerung zum single-thread). Aber 8 Threads auf einem single-core machen keinen Spass und zerhaut mir die Caches.

cu

Hi,

vielleicht hilft Dir der Artikel „Detecting Multi-Core Processor Topology in an IA-32 Platform“ von Intel weiter:
http://softwarecommunity.intel.com/articles/eng/2728…

Gruss,
Herb

Hallo,

Wie denn? In C? In C++?

Das wär mir sogar relativ wurscht. Das Projekt benutzt derzeit
eh beides. Ich muss nur wissen wieviele pthreads man
sinnvollerweise bauen kann. Das Ding scaliert sehr gut und
läuft auch bei 8 Kernen noch anständig (730% Steigerung zum
single-thread). Aber 8 Threads auf einem single-core machen
keinen Spass und zerhaut mir die Caches.

Die simplistische Variante:

#include 
#include 
#include 

 int num\_processors(const char\* fname)
{
 using namespace std;
 ifstream fh(fname); 
 if(!fh) return 0; 

 int n=0;
 string line; 
 string::size\_type p;
 while( getline(fh, line) ) 
 if((p=line.find( "processor", 0 )) != string::npos) ++n;

 return n;
}

 int main(int argc, char\*argv[])
{
 int n = num\_processors("/proc/cpuinfo");
 std::cout 

Man könnte natürlich auch die Geschwindigkeiten,
die Cache-Größen etc. auslesen, aber dafür würde
ich dann Boost\_Regex vorschlagen, da geht das
sehr einfach.

Grüße

CMБ
1 Like

Hallo

http://softwarecommunity.intel.com/articles/eng/2728…

Das ist sehr hübsch, danke für den Link.

Grüße

CMБ

Moien

Die simplistische Variante:

Da fehlt ein kleines Detail: „processor“ muss am Anfang der Zeile stehen sonst werden Dinge wie:
model name : Intel® Pentium® M processor 1.60GHz

mitgezählt.

Aber ich hab eine noch simplere Variante gefunden: /sys/devices/system/cpu/cpuX. Die haut auch auf nicht-Intels hin.

Danke

Hallo,

Die simplistische Variante:

Da fehlt ein kleines Detail: „processor“ muss am Anfang der
Zeile stehen sonst werden Dinge wie:
model name : Intel® Pentium® M processor 1.60GHzmitgezählt.

ersetze mal die „find“-Zeile mit

 ...
 if((p=line.find( "processor\t:", 0 )) != string::npos) ++n;
 ...

Aber ich hab eine noch simplere Variante gefunden:
/sys/devices/system/cpu/cpuX. Die haut auch auf nicht-Intels
hin.

Na ja, das mußt Du ja auch erstmal einlesen.

Ich hab jetzt mal die (o.g.) Intel-Sourcen verändert. Das
funktioniert bei mir (recht gut):

// [cpudetect.cxx]
// compile: g++ -DLINUX -o cpudetect cpudetect.cxx

#include 
 
 unsigned int num\_logical\_processors(bool verbose=true);

 int main()
{
 bool talkmuch = false;
 unsigned int n = num\_logical\_processors(talkmuch);
 
 if(talkmuch == false)
 printf("num\_logical\_processors returned: %d\n", n);

 return 0;
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //
// This is a modified and stripped down version of CPUCount.cpp, Copyright (c) 2005 Intel Corporation
// Original file is: softwarecommunity.intel.com/articles/eng/2728.htm
// Modified for machine readable output, compile: g++ -DLINUX -Wall -o cpudetect cpudetect.cxx

#define HWD\_MT\_BIT 0x10000000 // EDX[28] Bit 28 is set if HT or multi-core is supported
#define NUM\_LOGICAL\_BITS 0x00FF0000 // EBX[23:16] Bit 16-23 in ebx contains the number of logical
 // processors per physical processor when execute cpuid with eax set to 1
#define NUM\_CORE\_BITS 0xFC000000 // EAX[31:26] Bit 26-31 in eax contains the number of cores minus one
 // per physical processor when execute cpuid with 
 // eax set to 4. 
#define INITIAL\_APIC\_ID\_BITS 0xFF000000 // EBX[31:24] Bits 24-31 (8 bits) return the 8-bit unique 
 // initial APIC ID for the processor this code is running on.
// Status Flag
#define SINGLE\_CORE\_AND\_HT\_ENABLED 1
#define SINGLE\_CORE\_AND\_HT\_DISABLED 2
#define SINGLE\_CORE\_AND\_HT\_NOT\_CAPABLE 4
#define MULTI\_CORE\_AND\_HT\_NOT\_CAPABLE 5
#define MULTI\_CORE\_AND\_HT\_ENABLED 6
#define MULTI\_CORE\_AND\_HT\_DISABLED 7
#define USER\_CONFIG\_ISSUE 8

unsigned int CpuIDSupported(void);
unsigned int GenuineIntel(void);
unsigned int HWD\_MTSupported(void);
unsigned int MaxLogicalProcPerPhysicalProc(void);
unsigned int MaxCorePerPhysicalProc(void);
unsigned int find\_maskwidth(unsigned int);
unsigned char GetAPIC\_ID(void);
unsigned char GetNzbSubID(unsigned char, unsigned char, unsigned char);

unsigned char CPUCount(unsigned int \*, unsigned int \*, unsigned int \*);

// Define constant “LINUX” to compile under Linux
#ifdef LINUX
// The Linux source code listing can be compiled using Linux kernel verison 2.6 
// or higher (e.g. RH 4AS-2.8 using GCC 3.4.4). 
// Due to syntax variances of Linux affinity APIs with earlier kernel versions 
// and dependence on glibc library versions, compilation on Linux environment 
// with older kernels and compilers may require kernel patches or compiler upgrades.

#include 
#include 
#include 
#include 
#define DWORD unsigned long
#else
#include 
#endif

#include 

char g\_s3Levels[2048];

 unsigned int num\_logical\_processors(bool verbose)
{
 unsigned int TotAvailLogical = 0, // Number of available logical CPU per CORE
 TotAvailCore = 0, // Number of available cores per physical processor
 PhysicalNum = 0; // Total number of physical processors

 unsigned char StatusFlag = 0; 
 int MaxLPPerCore;
 if(CpuIDSupported() 1 ? "yes\n" : "No\n");
 break;
 case SINGLE\_CORE\_AND\_HT\_NOT\_CAPABLE:
 printf("Hyper-threading: No\nMulti-core: No\nMulti-processor: ");
 printf("%s", PhysicalNum \> 1 ? "yes\n" : "No\n");
 break;
 case SINGLE\_CORE\_AND\_HT\_DISABLED:
 printf("Hyper-threading: Disabled\nMulti-core: No\nMulti-processor: ");
 printf("%s", PhysicalNum \> 1 ? "yes\n" : "No\n");
 break;
 case SINGLE\_CORE\_AND\_HT\_ENABLED:
 printf("Hyper-threading: Yes\nMulti-core: No \nMulti-processor: ");
 printf("%s", PhysicalNum \> 1 ? "yes\n" : "No\n");
 break;
 case MULTI\_CORE\_AND\_HT\_DISABLED:
 printf("Hyper-threading: Disabled\nMulti-core: Yes\nMulti-processor: ");
 printf("%s", PhysicalNum \> 1 ? "yes\n" : "No\n");
 break;
 case MULTI\_CORE\_AND\_HT\_ENABLED:
 printf("Hyper-threading: Yes\nMulti-core: Yes\nMulti-processor: ");
 printf("%s", PhysicalNum \> 1 ? "yes\n" : "No\n");
 break;
 }

 MaxLPPerCore = MaxLogicalProcPerPhysicalProc() / MaxCorePerPhysicalProc() ;
 printf("Multi-core\_caps: %d cores per package \n", MaxCorePerPhysicalProc());
 printf("Hyper-threading\_caps: %d logical processors per core \n", MaxLPPerCore);
 assert (PhysicalNum \* MaxCorePerPhysicalProc() \>= TotAvailCore);
 assert (PhysicalNum \* MaxLogicalProcPerPhysicalProc() \>= TotAvailLogical);
 printf("Availability: %s cores in the system are enabled for this application.\n",
 (PhysicalNum\*MaxCorePerPhysicalProc() \> TotAvailCore) ? "Not all" : "All");
 
 return TotAvailLogical;
}

//
// CpuIDSupported will return 0 if CPUID instruction is unavailable. Otherwise, it will return 
// the maximum supported standard function.
//
 unsigned int CpuIDSupported(void)
{
 unsigned int MaxInputValue;
// If CPUID instruction is supported
#ifdef LINUX
 try 
 { 
 MaxInputValue = 0;
 // call cpuid with eax = 0
 asm
 ( 
 "xorl %%eax,%%eax\n\t"
 "cpuid\n\t"
 : "=a" (MaxInputValue)
 : 
 : "%ebx", "%ecx", "%edx"
 ); 
 }
 catch (...)
 {
 return(0); // cpuid instruction is unavailable
 }
#else //Win32
 try
 {
 MaxInputValue = 0;
 // call cpuid with eax = 0
 \_\_asm
 {
 xor eax, eax
 cpuid
 mov MaxInputValue, eax
 }
 }
 catch (...)
 {
 return(0); // cpuid instruction is unavailable
 }
#endif

 return MaxInputValue;
}

//
// GenuineIntel will return 0 if the processor is not a Genuine Intel Processor 
//
 unsigned int GenuineIntel(void)
{
#ifdef LINUX
 unsigned int VendorIDb = 0,VendorIDd = 0, VendorIDc = 0;

 try 
 // If CPUID instruction is supported
 {
 // Get vendor id string
 asm
 (
 //get the vendor string
 // call cpuid with eax = 0
 "xorl %%eax, %%eax\n\t" 
 "cpuid\n\t"
 : "=b" (VendorIDb),
 "=d" (VendorIDd),
 "=c" (VendorIDc)
 :
 : "%eax"
 );
 }

 catch(...)
 {
 return(0); // cpuid instruction is unavailable
 }

 return ( 
 (VendorIDb == 'uneG') &&
 (VendorIDd == 'Ieni') &&
 (VendorIDc == 'letn')
 ); 

#else
 unsigned int VendorID[3] = {0, 0, 0};
 try // If CPUID instruction is supported
 {
 \_\_asm 
 {
 xor eax, eax // call cpuid with eax = 0
 cpuid // Get vendor id string
 mov VendorID, ebx
 mov VendorID + 4, edx
 mov VendorID + 8, ecx
 }
 } 
 catch (...)
 {
 return(0); unsigned int MaxInputValue =0;
 // cpuid instruction is unavailable
 }
 return ( 
 (VendorID[0] == 'uneG') &&
 (VendorID[1] == 'Ieni') &&
 (VendorID[2] == 'letn')
 ); 
#endif
}

//
// Function returns the maximum cores per physical package. Note that the number of 
// AVAILABLE cores per physical to be used by an application might be less than this
// maximum value.
//

 unsigned int MaxCorePerPhysicalProc(void)
{
 unsigned int Regeax = 0;
 
 if( ! HWD\_MTSupported() ) 
 return (unsigned int) 1; // Single core
#ifdef LINUX
 {
 asm
 (
 "xorl %eax, %eax\n\t"
 "cpuid\n\t"
 "cmpl $4, %eax\n\t" // check if cpuid supports leaf 4
 "jl .single\_core\n\t" // Single core
 "movl $4, %eax\n\t" 
 "movl $0, %ecx\n\t" // start with index = 0; Leaf 4 reports
 ); // at least one valid cache level
 asm
 (
 "cpuid"
 : "=a" (Regeax)
 :
 : "%ebx", "%ecx", "%edx"
 ); 
 asm
 (
 "jmp .multi\_core\n"
 ".single\_core:\n\t"
 "xor %eax, %eax\n"
 ".multi\_core:"
 ); 
 }
#else
 \_\_asm
 {
 xor eax, eax
 cpuid
 cmp eax, 4 // check if cpuid supports leaf 4
 jl single\_core // Single core
 mov eax, 4 
 mov ecx, 0 // start with index = 0; Leaf 4 reports
 cpuid // at least one valid cache level
 mov Regeax, eax
 jmp multi\_core
single\_core:
 xor eax, eax 
multi\_core:
 }
#endif

 return (unsigned int)((Regeax & NUM\_CORE\_BITS) \>\> 26)+1;
}

//
// The function returns 0 when the hardware multi-threaded bit is not set.
//
 unsigned int HWD\_MTSupported(void)
{
 unsigned int Regedx = 0;
 if ((CpuIDSupported() \>= 1) && GenuineIntel()) {
#ifdef LINUX
 asm 
 (
 "movl $1,%%eax\n\t"
 "cpuid"
 : "=d" (Regedx)
 :
 : "%eax","%ebx","%ecx"
 );
#else
 \_\_asm
 {
 mov eax, 1
 cpuid
 mov Regedx, edx
 } 
#endif
 }

 return (Regedx & HWD\_MT\_BIT); 
}

//
// Function returns the maximum logical processors per physical package. Note that the number of 
// AVAILABLE logical processors per physical to be used by an application might be less than this
// maximum value.
//
 unsigned int MaxLogicalProcPerPhysicalProc(void)
{
 unsigned int Regebx = 0;

 if( ! HWD\_MTSupported() ) 
 return (unsigned int) 1;
#ifdef LINUX
 asm 
 (
 "movl $1,%%eax\n\t"
 "cpuid"
 : "=b" (Regebx)
 :
 : "%eax","%ecx","%edx"
 );
#else
 \_\_asm
 {
 mov eax, 1
 cpuid
 mov Regebx, ebx
 }
#endif

 return (unsigned int) ((Regebx & NUM\_LOGICAL\_BITS) \>\> 16);
}


 unsigned char GetAPIC\_ID(void)
{
 unsigned int Regebx = 0;
#ifdef LINUX
 asm
 (
 "movl $1, %%eax\n\t" 
 "cpuid"
 : "=b" (Regebx) 
 :
 : "%eax","%ecx","%edx" 
 );

#else
 \_\_asm
 {
 mov eax, 1
 cpuid
 mov Regebx, ebx
 }
#endif 

 return (unsigned char) ((Regebx & INITIAL\_APIC\_ID\_BITS) \>\> 24);
}

//
// Determine the width of the bit field that can represent the value count\_item. 
//
 unsigned int find\_maskwidth(unsigned int CountItem)
{
 unsigned int MaskWidth, count = CountItem;
#ifdef LINUX
 asm
 (
#ifdef \_\_x86\_64\_\_ // define constant to compile 
 "push %%rcx\n\t" // under 64-bit Linux
 "push %%rax\n\t"
#else
 "pushl %%ecx\n\t"
 "pushl %%eax\n\t"
#endif
// "movl $count, %%eax\n\t" // done by Assembler below
 "xorl %%ecx, %%ecx"
// "movl %%ecx, MaskWidth\n\t" // done by Assembler below
 : "=c" (MaskWidth)
 : "a" (count)
// : "%ecx", "%eax" We don't list these as clobbered because we don't want the assembler
// to put them back when we are done
 );
 asm
 (
 "decl %%eax\n\t"
 "bsrw %%ax,%%cx\n\t"
 "jz next\n\t"
 "incw %%cx\n\t"
// "movl %%ecx, MaskWidth\n" // done by Assembler below
 : "=c" (MaskWidth)
 :
 );
 asm
 (
 "next:\n\t"
#ifdef \_\_x86\_64\_\_
 "pop %rax\n\t"
 "pop %rcx" 
#else
 "popl %eax\n\t"
 "popl %ecx" 
#endif
 );

#else
 \_\_asm
 {
 mov eax, count
 mov ecx, 0
 mov MaskWidth, ecx
 dec eax
 bsr cx, ax
 jz next
 inc cx
 mov MaskWidth, ecx
next:

 }
#endif
 return MaskWidth;
}

//
// Extract the subset of bit field from the 8-bit value FullID. It returns the 8-bit sub ID value
//
 unsigned char GetNzbSubID(unsigned char FullID, unsigned char MaxSubIDValue, unsigned char ShiftCount)
{
 unsigned int MaskWidth;
 unsigned char MaskBits;

 MaskWidth = find\_maskwidth((unsigned int) MaxSubIDValue);
 MaskBits = (0xff \*PhysicalNum) {
 // Multi-core
 if(MaxLPPerCore == 1)
 StatusFlag = MULTI\_CORE\_AND\_HT\_NOT\_CAPABLE;
 else if(numLPEnabled \> \*TotAvailCore)
 StatusFlag = MULTI\_CORE\_AND\_HT\_ENABLED;
 else 
 StatusFlag = MULTI\_CORE\_AND\_HT\_DISABLED;
 }
 else {
 // Single-core
 if(MaxLPPerCore == 1)
 StatusFlag = SINGLE\_CORE\_AND\_HT\_NOT\_CAPABLE;
 else if(numLPEnabled \> \*TotAvailCore)
 StatusFlag = SINGLE\_CORE\_AND\_HT\_ENABLED;
 else 
 StatusFlag = SINGLE\_CORE\_AND\_HT\_DISABLED;
 }

 return StatusFlag;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //

Grüße

CMБ