Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2012-12

Feature announcement: Extension of TThread's interface

40 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Sven Barth

Hello Free Pascal community!

I'm pleased to announce the extension of TThread's interface to bring it more on par with current Delphi versions.

Extensions:

Note: in the following list "class" means that the property or method is a class property or method and thus can be called without a specific TThread instance.

New properties:

- Finished:
Returns whether the thread has finished it's execution whereas it does not depend on whether the thread finished itself or an exception happened.
- CurrentThread (class):
Returns a TThread instance of the current thread even if the thread wasn't originally started through a TThread instance. This is useful if you have some thread aware procedure and function which then needs access to the TThread instance to do a Synchronize or Queue call. For external threads a TThread instance is created on the fly and freed at the end of the application (see also Future Developments).
- ExternalThread:
Returns whether the thread was not started through a TThread instance (or one of its descendants), but was started from an external source. Examples when this is true is for threads created by BeginThread, for the main thread and threads created by libraries. See also CurrentThread.
- ProcessorCount (class):
Returns the count of CPU cores detected by the RTL. This is based on the new global property System.GetCPUCount which needs to be implemented per target. Currently only a default implementation exists which returns "1".
- IsSingleProcessor (class):
Returns whether the application is running on a single processor system.

New methods:

- GetTickCount (class, deprecated):
Returns the value of SysUtils.GetTickCount.
- GetTickCount64 (class):
Returns the value of SysUtils.GetTickCount64.
- Yield (class):
Calls System.ThreadSwitch to give another thread (maybe even from another process) the change to do its work.
- CheckTerminated (class):
Returns the value of TThread.Terminated of the current thread if the thread was created using TThread or raises an
EThreadExternalException otherwise.
- SetReturnValue (class):
Allows to set the value returned by TThread.WaitFor for the current thread if the thread was created using TThread or raises an EThreadExternalException otherwise.
- SpinWait (class):
Does a busy wait for the given amount of iterations (useful to burn just a few CPU cycles).
- CreateAnonymousThread (class):
Creates a new TThread instance based on a global procedure. The thread is started suspended and with FreeOnTerminate set. Use Start on the returned TThread instance to start the thread's execution.
- GetSystemTimes (class):
This fills a TThread.TSystemTimes record with the time the process has spend in different states. This method is platform specific and by default just zeros the record.
- NameThreadForDebugging (class):
This gives the thread with the given thread ID (or the current thread if the ID is -1) the given name. This way the thread can be easily identified when debugging. This method is platform specific and by default it does nothing.
- Queue (class):
The given method pointer is added to a queue that is processed by CheckSynchronize and therefore executed inside the main thread. Unlike Synchronize this is not a blocking call. If the thread instance is Nil the thread is determined using TThread.CurrentThread. See also CheckSynchronize.
- Queue (protected):
The same as the class method Queue, but with the difference that always the current TThread instance (Self) is used.
- RemoveQueuedEvents (class):
If a TThread instance is given all queued methods (excluding Synchronize ones) of that thread are removed from the queue processed by CheckSynchronize. If no thread is given, but a method pointer all queued entries (excluding Synchronize ones) with that method are removed no matter which thread added them. If both the thread and the method is given the thread takes precedence.

CheckSynchronize:

This function now processes a complete queue of thread events (queued by either TThread.Synchronize or TThread.Queue) unlike before where only a single event was handled. Like before if an Exception happens inside a method added by Synchronize the exception is passed back to the calling method. For methods added by Queue the exception is raised (after the queued entry was removed from the queue).

For platform developers:

Unlike implementing directly TThread's constructor and destructor new methods SysCreate and SysDestroy were added which must be implemented for platform specific initialization/finialization of a thread.

All platform maintainers should check whether their platforms still compile and - if it supports multi threading - still runs correctly. At least Unix and Windows platforms do compile and Unix platforms do run.

Future developments:

Currently a usage of TThread.CurrentThread inside an external thread will create a TThread instance that exists till the end of the program. Using notification mechanism provided by the threading implementation (TLS entry on Windows and thread destroy callbacks for pthreads) one can make the extension that such instances are freed once the corresponding external thread terminates. For other platforms the collector provided in the following bug report could be used:
http://bugs.freepascal.org/view.php?id=17300 (comment 47406)

The methods NameThreadForDebugging and GetSystemTimes need to be implemented for those platforms that support it.

Once anonymous procedures are supported the argument for CreateAnonymousThread will be adjusted and corresponding overloads for Synchronize and Queue will be added.

Maybe in the future a look at extending the language with keywords that were introduced for Oxygene can be done (see
http://wiki.freepascal.org/OpenMP_support#Proposal_3 )

Regards,
Sven

Reply by email

Ewald
to Sven Barth

Great! Keep up the good work ;-)

Rather funny actually... Quite some time ago I wrote my own threading mechanism and decided to break compatibility with fpc's TThread interface. Ever since I did that my own interface somehow became more and more compatible again with the implementation of TThread in fpc.... If I wait any longer I can simply switch back to native implementation again :-)

Now, for the implementation of ProcessorCount I've got code here that reads the amount of processor cores from `/proc/cpuinfo` (linux only I think) and some assembly code [asmmode att] (tested on x86_64 and i386) that *tries* to get the amount of cpu cores by the use of CPUID. The only problem with the last one is that it isn't 100% correct, on an i7 for example, you get 16 as a result, where the result should be 8. Problem is that it is quite a lot of work to get the function to work decently, and since I didn't really was in the mood, I never fixed it (shame on me...).

Anyway, this last one could shurely be used as some kind of all-round implementation for CPU's that support CPUID in `IsSingleProcessor`.

If you (or anybody else) is interested, just let me know.

Once upon a time, on 12/27/2012 05:23 PM to be precise, Sven Barth said:

Show quoted text 6 lines
Hello Free Pascal community! I'm pleased to announce the extension of TThread's interface to bring it more on par with current Delphi versions. [snip]
Ewald

Reply by email

Mark Morgan Lloyd
to Ewald
Ewald wrote
Now, for the implementation of ProcessorCount I've got code here that reads the amount of processor cores from `/proc/cpuinfo` (linux only I think) and some assembly code [asmmode att] (tested on x86_64 and i386) that *tries* to get the amount of cpu cores by the use of CPUID. The

In the general case, you have to be careful with this since (a) every architecture puts different info in /proc/cpuinfo and (b) the processor numbering and affinity vectors can have gaps.

type : sun4u
ncpus probed : 12
ncpus active : 12
..
CPU0: online
CPU1: online
CPU4: online
CPU5: online
CPU8: online
CPU9: online
CPU10: online
CPU11: online
CPU12: online
CPU13: online
CPU14: online
CPU15: online

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Marco van de Voort
to Sven Barth: Hello Free Pascal community! I'm pleased to announce the extension of TThread's interface…

In our previous episode, Sven Barth said:

Show quoted text 5 lines
- ProcessorCount (class): Returns the count of CPU cores detected by the RTL. This is based on the new global property System.GetCPUCount which needs to be implemented per target. Currently only a default implementation exists which returns "1".

Here is some BSD code. I don't know what it returns, physical or virtual cores since the machine I developed it with has no physical ones.

The hw.* mib might vary slightly with the BSD flavour. The pchar casts are probably due to a bug in the FPC sysctl unit.

uses baseunix,sysctl,ctypes;
var mib : array[0..3] of cint;
    len : cint;
    numcpu:cint;
begin
len:= sizeof(numCPU);
{ set the mib for hw.ncpu }
mib[0] := CTL_HW;
mib[1] := HW_NCPU;  // alternatively, try HW_AVAILCPU;
{ get the number of CPUs from the system }
fpsysctl(pchar(@mib), 2, @numCPU, @len, NIL, 0);
if( numCPU < 1 ) then
begin
     mib[1] := HW_NCPU;
     fpsysctl( pchar(@mib), 2, @numCPU, @len, NIL, 0 );
     if( numCPU < 1 ) then
     begin
          numCPU := 1;
     end;
end;
 writeln(numCPU);
end.

Reply by email

Ewald
to Mark Morgan Lloyd: In the general case, you have to be careful with this since (a) every architecture puts…

Hmmm, that;s indeed quite some different output you've got there. Mine looks like this:

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz stepping : 10
microcode : 0xa07
cpu MHz : 2000.000
cache size : 6144 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 2
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm tpr_shadow vnmi flexpriority bogomips : 6668.63
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual power management:

(this is repeated twice, with only `processor:0` changing to `processor:1`)

Since this is the same kind of output I got on several other linux distributions/architectures(--> 32 bit versus 64 bit intel), I assumed it was kinda `standard`. Then again assume = ...

Well, anyway, it's a bit trickier than I thought at first in that case.

Once upon a time, on 12/27/2012 08:01 PM to be precise, Mark Morgan Lloyd said:

Show quoted text 28 lines
Ewald wrote: > Now, for the implementation of ProcessorCount I've got code here that > reads the amount of processor cores from `/proc/cpuinfo` (linux only I > think) and some assembly code [asmmode att] (tested on x86_64 and i386) > that *tries* to get the amount of cpu cores by the use of CPUID. The In the general case, you have to be careful with this since (a) every architecture puts different info in /proc/cpuinfo and (b) the processor numbering and affinity vectors can have gaps. type : sun4u ncpus probed : 12 ncpus active : 12 .. CPU0: online CPU1: online CPU4: online CPU5: online CPU8: online CPU9: online CPU10: online CPU11: online CPU12: online CPU13: online CPU14: online CPU15: online
Ewald

Reply by email

Ewald
to Mark Morgan Lloyd: In the general case, you have to be careful with this since (a) every architecture puts…

Right, since the /proc/cpuinfo (a) is not available on many platforms and (b) has no standard output format, I decided to fix the half done CPUID approach. Here it goes (note: don't shoot me if my assembly is a bit weird, I've only learned part of it by experimenting): [see below]

For time being there are only two CPU kinds supported (GenuineIntel and AuthenticAMD), in other cases it returns the # of logical CPU's. Feel free to extend the code with other CPU ID's ;-)

Oh, and the important part: The function has been tested on a Core 2 Duo and an Intel i7, and works correctly. If someone would be so kind to test it on some other CPU's that would be great! [I'm not 100% of the hexadecimal of `AuthenticAMD` you see]

program cpucount;
{$mode objfpc}
{$asmmode att}

Function GetCores: LongWord;
Begin
Asm

        //Vendor ID
        MOV $0, %eax
        MOV $0, %ecx
        CPUID
        // ?= GenuineIntel
        CMP $0x756e6547, %ebx
        JNE .LnotGenuineIntel
        CMP $0x49656e69, %edx
        JNE .LnotGenuineIntel
        CMP $0x6c65746e, %ecx
        JNE .LnotGenuineIntel
        MOV $4, %eax
        MOV $0, %ecx
        CPUID
        SHR $26, %eax
        AND $0x3F, %eax
        ADD $1, %eax
        MOV %eax, __RESULT
        JMP .LReturn
        .LnotGenuineIntel:
        // ?= AuthenticAMD
        CMP $0x68747541, %ebx
        JNE .LnotAuthenticAMD
        CMP $0x69746e65, %edx
        JNE .LnotAuthenticAMD
        CMP $0x444d4163, %ecx
        JNE .LnotAuthenticAMD
        MOV $0x80000008, %eax
        MOV $0, %ecx
        CPUID
        AND $0xFF, %ecx
        ADD $1, %ecx
        MOV %ecx, __RESULT
        JMP .LReturn
        .LnotAuthenticAMD:
        //Return #logical CPU's
        MOV $1, %eax
        MOV $0, %ecx
        CPUID
        SHR $16, %ebx
        AND $0xFF, %ebx
        MOV %ebx, __RESULT
        .LReturn:
    End ['eax', 'ebx', 'ecx', 'edx'];
End;
Begin
    Writeln('#CPU cores: ', GetCores);
End.
Ewald

Reply by email

Mattias Gaertner
to Ewald
Show quoted text 14 lines
Right, since the /proc/cpuinfo (a) is not available on many platforms and (b) has no standard output format, I decided to fix the half done CPUID approach. Here it goes (note: don't shoot me if my assembly is a bit weird, I've only learned part of it by experimenting): [see below] For time being there are only two CPU kinds supported (GenuineIntel and AuthenticAMD), in other cases it returns the # of logical CPU's. Feel free to extend the code with other CPU ID's ;-) Oh, and the important part: The function has been tested on a Core 2 Duo and an Intel i7, and works correctly. If someone would be so kind to test it on some other CPU's that would be great! [I'm not 100% of the hexadecimal of `AuthenticAMD` you see]

It gives 4 correctly for an AMD Phenom(tm) II X4 965 Processor.

Mattias

Show quoted text 71 lines
program cpucount; {$mode objfpc} {$asmmode att} Function GetCores: LongWord; Begin Asm //Vendor ID MOV $0, %eax MOV $0, %ecx CPUID // ?= GenuineIntel CMP $0x756e6547, %ebx JNE .LnotGenuineIntel CMP $0x49656e69, %edx JNE .LnotGenuineIntel CMP $0x6c65746e, %ecx JNE .LnotGenuineIntel MOV $4, %eax MOV $0, %ecx CPUID SHR $26, %eax AND $0x3F, %eax ADD $1, %eax MOV %eax, __RESULT JMP .LReturn .LnotGenuineIntel: // ?= AuthenticAMD CMP $0x68747541, %ebx JNE .LnotAuthenticAMD CMP $0x69746e65, %edx JNE .LnotAuthenticAMD CMP $0x444d4163, %ecx JNE .LnotAuthenticAMD MOV $0x80000008, %eax MOV $0, %ecx CPUID AND $0xFF, %ecx ADD $1, %ecx MOV %ecx, __RESULT JMP .LReturn .LnotAuthenticAMD: //Return #logical CPU's MOV $1, %eax MOV $0, %ecx CPUID SHR $16, %ebx AND $0xFF, %ebx MOV %ebx, __RESULT .LReturn: End ['eax', 'ebx', 'ecx', 'edx']; End; Begin Writeln('#CPU cores: ', GetCores); End.

Reply by email

Unknown author
to Mark Morgan Lloyd: In the general case, you have to be careful with this since (a) every architecture puts…
Mark Morgan Lloyd wrote 10 lines
Ewald wrote: >Now, for the implementation of ProcessorCount I've got code here that >reads the amount of processor cores from `/proc/cpuinfo` (linux only I >think) and some assembly code [asmmode att] (tested on x86_64 and i386) >that *tries* to get the amount of cpu cores by the use of CPUID. The In the general case, you have to be careful with this since (a) every architecture puts different info in /proc/cpuinfo and (b) the processor numbering and affinity vectors can have gaps.

In the general case how is his x86 asm supposed to ever work on anything but Intel or AMD boxes?

Show quoted text 17 lines
type : sun4u ncpus probed : 12 ncpus active : 12 .. CPU0: online CPU1: online CPU4: online CPU5: online CPU8: online CPU9: online CPU10: online CPU11: online CPU12: online CPU13: online CPU14: online CPU15: online

Looks like a weird bug in the probing. Why does it miss CPs 2,3,6,7?

Reply by email

Ludo Brands
to Ewald: Right, since the /proc/cpuinfo (a) is not available on many platforms and (b) has no…
Ewald wrote 5 lines
Oh, and the important part: The function has been tested on a Core 2 Duo and an Intel i7, and works correctly. If someone would be so kind to test it on some other CPU's that would be great! [I'm not 100% of the hexadecimal of `AuthenticAMD` you see]

Inconsistent results here with hyperthreading:
Xeon W3530 (4 cores hyperthreading) reports #CPU cores: 8. /proc/cpuinfo lists 8 processors and 4 cpu cores
Intel Atom 230 (1 core hyperthreading) reports #CPU cores: 1 while /proc/cpuinfo reports 2 processors and 1 cpu core.

processor : 7
vendor_id : GenuineIntel
cpu family : 6
model : 26
model name : Intel(R) Xeon(R) CPU W3530 @ 2.80GHz stepping : 5
microcode : 0x11
cpu MHz : 2801.000
cache size : 8192 KB
physical id : 0
siblings : 8
core id : 3
cpu cores : 4
....

processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 28
model name : Intel(R) Atom(TM) CPU 230 @ 1.60GHz stepping : 2
cpu MHz : 1599.570
cache size : 512 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
....

AMD Athlon X2 5600+ reports #CPU cores: 2. /proc/cpuinfo reports 2 processors and 2 cores.

Ludo

Reply by email

Mark Morgan Lloyd
to Ludo Brands
Ludo Brands wrote 14 lines
On 27/12/2012 23:06, Ewald wrote: > Oh, and the important part: The function has been tested on a Core 2 Duo > and an Intel i7, and works correctly. If someone would be so kind to > test it on some other CPU's that would be great! [I'm not 100% of the > hexadecimal of `AuthenticAMD` you see] > Inconsistent results here with hyperthreading: Xeon W3530 (4 cores hyperthreading) reports #CPU cores: 8. /proc/cpuinfo lists 8 processors and 4 cpu cores Intel Atom 230 (1 core hyperthreading) reports #CPU cores: 1 while /proc/cpuinfo reports 2 processors and 1 cpu core. AMD Athlon X2 5600+ reports #CPU cores: 2. /proc/cpuinfo reports 2 processors and 2 cores.

Also be careful of the situation where an OS supports hot-pluggable CPU cards and has been told to shut one down for maintenance. Solaris definitely does this on SPARC, I don't know about its position on x86, and I don't know about Linux's general position.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mark Morgan Lloyd
to Unknown author: In the general case how is his x86 asm supposed to ever work on anything but Intel or AMD…
Show quoted text 13 lines
On Thu, Dec 27, 2012 at 07:01:08PM +0000, Mark Morgan Lloyd wrote: > Ewald wrote: > >> Now, for the implementation of ProcessorCount I've got code here that >> reads the amount of processor cores from `/proc/cpuinfo` (linux only I >> think) and some assembly code [asmmode att] (tested on x86_64 and i386) >> that *tries* to get the amount of cpu cores by the use of CPUID. The > In the general case, you have to be careful with this since (a) > every architecture puts different info in /proc/cpuinfo and (b) the > processor numbering and affinity vectors can have gaps. In the general case how is his x86 asm supposed to ever work on anything but Intel or AMD boxes?

..

Looks like a weird bug in the probing. Why does it miss CPs 2,3,6,7?

Because on that architecture every board, when initialising, starts off by running independently and gets an ID from its slot position. One slot (slot 1, not 0) is taken up by the mandatory card which has things like keyboard, serial and diagnostic JTAG support, and another (slot 3 on the system here) by a card with enough SCSI and Ethernet to boot. Once all cards have decided they're OK, the first card sends JTAG commands to the bus controllers on every card to rewire them to distribute resources over the centerplane, but the CPU IDs persist through to the process and interrupt affinity vectors (the taskset command on Linux).

Even on something like an Ultra-60 there's a gap:

$ taskset -p 1
pid 1's current affinity mask: 5
$ taskset -p -c 1
pid 1's current affinity list: 0,2

I'm not sure about this, but I /think/ that counting the bits in those vectors is the safest approach. However I've not gone into the API and I don't know how long the vector gets: I'd expect it to be able to handle

32 CPUs (or cores) since I believe much of the work here was done by SGI.
Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Unknown author
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 27 lines
wrote: >On Thu, Dec 27, 2012 at 07:01:08PM +0000, Mark Morgan Lloyd wrote: >>Ewald wrote: >> >>>Now, for the implementation of ProcessorCount I've got code here that >>>reads the amount of processor cores from `/proc/cpuinfo` (linux only I >>>think) and some assembly code [asmmode att] (tested on x86_64 and i386) >>>that *tries* to get the amount of cpu cores by the use of CPUID. The >>In the general case, you have to be careful with this since (a) >>every architecture puts different info in /proc/cpuinfo and (b) the >>processor numbering and affinity vectors can have gaps. > >In the general case how is his x86 asm supposed to ever work on anything but >Intel or AMD boxes? .. >Looks like a weird bug in the probing. Why does it miss CPs 2,3,6,7? Because on that architecture every board, when initialising, starts off by running independently and gets an ID from its slot position. One slot (slot 1, not 0) is taken up by the mandatory card which has things like keyboard, serial and diagnostic JTAG support, and another (slot 3 on the system here) by a card with enough SCSI and Ethernet to boot. Once all cards have decided they're OK, the first card sends JTAG commands to the bus controllers on every card to rewire them to distribute resources over the centerplane, but the CPU IDs persist through to the process and interrupt affinity vectors (the taskset command on Linux).

Oh sorry, I misunderstood your post. I thought you meant only 12 of 16 CPUs were showing in Linux. If you only have 12 CPUs in this case then I understand the explanation. I seem to remember a discussion where you said you have a box with 16 sockets.

Reply by email

Mark Morgan Lloyd
to Mark Morgan Lloyd: Also be careful of the situation where an OS supports hot-pluggable CPU cards and has…
Mark Morgan Lloyd wrote 20 lines
Ludo Brands wrote: > On 27/12/2012 23:06, Ewald wrote: >> Oh, and the important part: The function has been tested on a Core 2 Duo >> and an Intel i7, and works correctly. If someone would be so kind to >> test it on some other CPU's that would be great! [I'm not 100% of the >> hexadecimal of `AuthenticAMD` you see] >> > Inconsistent results here with hyperthreading: > Xeon W3530 (4 cores hyperthreading) reports #CPU cores: 8. > /proc/cpuinfo lists 8 processors and 4 cpu cores > Intel Atom 230 (1 core hyperthreading) reports #CPU cores: 1 while > /proc/cpuinfo reports 2 processors and 1 cpu core. > AMD Athlon X2 5600+ reports #CPU cores: 2. /proc/cpuinfo reports 2 > processors and 2 cores. Also be careful of the situation where an OS supports hot-pluggable CPU cards and has been told to shut one down for maintenance. Solaris definitely does this on SPARC, I don't know about its position on x86, and I don't know about Linux's general position.

Also somebody needs to check the situation with VMWare, Qemu etc., since they might be uncomfortable virtualising CPUID.

I've just checked and taskset is supported on zLinux, so I'm fairly confident that the API that underlies it is universal on Linux 2.6+: I really do think that that's what should be used for this job.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

patspiper
to Ewald: Hmmm, that;s indeed quite some different output you've got there. Mine looks like this:…
Ewald wrote 43 lines
Hmmm, that;s indeed quite some different output you've got there. Mine looks like this: processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 23 model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz stepping : 10 microcode : 0xa07 cpu MHz : 2000.000 cache size : 6144 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm tpr_shadow vnmi flexpriority bogomips : 6668.63 clflush size : 64 cache_alignment : 64 address sizes : 36 bits physical, 48 bits virtual power management: (this is repeated twice, with only `processor:0` changing to `processor:1`) Since this is the same kind of output I got on several other linux distributions/architectures(--> 32 bit versus 64 bit intel), I assumed it was kinda `standard`. Then again assume = ... Well, anyway, it's a bit trickier than I thought at first in that case.

I guess one way of calculating the number of processors is to iterate through every 'processor' in the list and add 1 if 'siblings' = 'cpu cores' (no hyperthreading), and 0.5 if 'siblings' = 2 x 'cpu cores' (hyperthreading enabled).

Despite your listing of cpuinfo is partial, one can deduce that you don't have hyperthreading.

Stephano

Reply by email

Marco van de Voort
to Mark Morgan Lloyd: Also somebody needs to check the situation with VMWare, Qemu etc., since they might be…

In our previous episode, Mark Morgan Lloyd said:

Show quoted text 10 lines
> cards and has been told to shut one down for maintenance. Solaris > definitely does this on SPARC, I don't know about its position on x86, > and I don't know about Linux's general position. Also somebody needs to check the situation with VMWare, Qemu etc., since they might be uncomfortable virtualising CPUID. I've just checked and taskset is supported on zLinux, so I'm fairly confident that the API that underlies it is universal on Linux 2.6+: I really do think that that's what should be used for this job.

Note that in applications this should never be used for more than the default of a configurable option anyway.

The way new processors deal with this, can change at any time, and not making this configurable would seriously limit the durability of the software.

Reply by email

Mark Morgan Lloyd
to Marco van de Voort
Marco van de Voort wrote 17 lines
In our previous episode, Mark Morgan Lloyd said: >> cards and has been told to shut one down for maintenance. Solaris >> definitely does this on SPARC, I don't know about its position on x86, >> and I don't know about Linux's general position. > Also somebody needs to check the situation with VMWare, Qemu etc., since > they might be uncomfortable virtualising CPUID. > > I've just checked and taskset is supported on zLinux, so I'm fairly > confident that the API that underlies it is universal on Linux 2.6+: I > really do think that that's what should be used for this job. Note that in applications this should never be used for more than the default of a configurable option anyway. The way new processors deal with this, can change at any time, and not making this configurable would seriously limit the durability of the software.

If the number of CPUs changed during the lifetime of an app, it would need to know the current situation rather than the original one.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Ewald
to Ludo Brands: Inconsistent results here with hyperthreading: Xeon W3530 (4 cores hyperthreading)…

Hmmm, that's weird. The results of the Xeon are what I was expecting.

Quite frankly I don't know how to fix it. Maybe getting the maximum amount of threads sharing the caches might prove helpfull, but then again it is guesswork. Anyway, can you give this code a try?

Than if I take the highest value from this and the previous program it *might* provide a sensible result. (?)

program cpucount;
{$mode objfpc}
{$asmmode att}

Function GetCores: LongWord;
Var cnt: LongWord;
Begin
Asm
MOV $0, __RESULT
MOV $0, cnt
.LStart:
MOV $4, %eax
MOV cnt, %ecx
CPUID

MOV %eax, %ebx
SHR $14, %ebx
AND $0xFFF, %ebx
ADD $1, %ebx
CMP __RESULT, %ebx
JLE .LLessOrEqual
MOV %ebx, __RESULT

.LLessOrEqual:
AND $0xF, %eax

ADD $1, cnt

        CMP $0, %eax
        JNE .LStart
    End ['eax', 'ebx', 'ecx', 'edx'];
End;
Begin
    Writeln('#max threads sharing caches: ', GetCores);
End.

Once upon a time, on 12/28/2012 08:12 AM to be precise, Ludo Brands said:

Show quoted text 47 lines
Inconsistent results here with hyperthreading: Xeon W3530 (4 cores hyperthreading) reports #CPU cores: 8. /proc/cpuinfo lists 8 processors and 4 cpu cores Intel Atom 230 (1 core hyperthreading) reports #CPU cores: 1 while /proc/cpuinfo reports 2 processors and 1 cpu core. processor : 7 vendor_id : GenuineIntel cpu family : 6 model : 26 model name : Intel(R) Xeon(R) CPU W3530 @ 2.80GHz stepping : 5 microcode : 0x11 cpu MHz : 2801.000 cache size : 8192 KB physical id : 0 siblings : 8 core id : 3 cpu cores : 4 .... processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 28 model name : Intel(R) Atom(TM) CPU 230 @ 1.60GHz stepping : 2 cpu MHz : 1599.570 cache size : 512 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 1 .... AMD Athlon X2 5600+ reports #CPU cores: 2. /proc/cpuinfo reports 2 processors and 2 cores. Ludo _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel
Ewald

Reply by email

Ewald
to Mark Morgan Lloyd: Also be careful of the situation where an OS supports hot-pluggable CPU cards and has…

Once upon a time, on 12/28/2012 09:29 AM to be precise, Mark Morgan Lloyd said:

Show quoted text 21 lines
Ludo Brands wrote: > On 27/12/2012 23:06, Ewald wrote: >> Oh, and the important part: The function has been tested on a Core 2 >> Duo >> and an Intel i7, and works correctly. If someone would be so kind to >> test it on some other CPU's that would be great! [I'm not 100% of the >> hexadecimal of `AuthenticAMD` you see] >> > Inconsistent results here with hyperthreading: > Xeon W3530 (4 cores hyperthreading) reports #CPU cores: 8. > /proc/cpuinfo lists 8 processors and 4 cpu cores > Intel Atom 230 (1 core hyperthreading) reports #CPU cores: 1 while > /proc/cpuinfo reports 2 processors and 1 cpu core. > AMD Athlon X2 5600+ reports #CPU cores: 2. /proc/cpuinfo reports 2 > processors and 2 cores. Also be careful of the situation where an OS supports hot-pluggable CPU cards and has been told to shut one down for maintenance. Solaris definitely does this on SPARC, I don't know about its position on x86, and I don't know about Linux's general position.

Well, the code I posted here doesn't take this sort of hotplugging in account, since it returns the # processor cores per physical cpu. Also when software shuts down cpu cores these aren't reflected in the result of the function. (says intel documentation)

Ewald

Reply by email

Ewald
to patspiper: I guess one way of calculating the number of processors is to iterate through every…

Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said:

Show quoted text 50 lines
On 27/12/12 22:38, Ewald wrote: > Hmmm, that;s indeed quite some different output you've got there. > Mine looks like this: > > processor : 0 > vendor_id : GenuineIntel > cpu family : 6 > model : 23 > model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz > stepping : 10 > microcode : 0xa07 > cpu MHz : 2000.000 > cache size : 6144 KB > physical id : 0 > siblings : 2 > core id : 0 > cpu cores : 2 > apicid : 0 > initial apicid : 0 > fpu : yes > fpu_exception : yes > cpuid level : 13 > wp : yes > flags : fpu vme de pse tsc msr pae mce cx8 apic sep > mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss > ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts > rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est > tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm tpr_shadow > vnmi flexpriority > bogomips : 6668.63 > clflush size : 64 > cache_alignment : 64 > address sizes : 36 bits physical, 48 bits virtual > power management: > > > (this is repeated twice, with only `processor:0` changing to > `processor:1`) > > > Since this is the same kind of output I got on several other linux > distributions/architectures(--> 32 bit versus 64 bit intel), I > assumed it was kinda `standard`. Then again assume = ... > > Well, anyway, it's a bit trickier than I thought at first in that case. I guess one way of calculating the number of processors is to iterate through every 'processor' in the list and add 1 if 'siblings' = 'cpu cores' (no hyperthreading), and 0.5 if 'siblings' = 2 x 'cpu cores' (hyperthreading enabled).

Yeah, that could work, but then again the actual format of the data may be different measured over several distributions: suppose all `:` all of the sudden become `=`? Suppose that an identifier like `processor` undergoes a slicht namechange to `processorid`?

As I said, I didn't know formats of /proc/cpuinfo differ over distributions/os'es, so it isn't safe to use this approach since all of the sudden a simly system update *might* just break your application.

Despite your listing of cpuinfo is partial, one can deduce that you don't have hyperthreading.

Quite right. :-)

Ewald

Reply by email

Ewald
to Unknown author: In the general case how is his x86 asm supposed to ever work on anything but Intel or AMD…

Once upon a time, on 12/28/2012 06:46 AM to be precise, said:

Show quoted text 12 lines
On Thu, Dec 27, 2012 at 07:01:08PM +0000, Mark Morgan Lloyd wrote: > Ewald wrote: > >> Now, for the implementation of ProcessorCount I've got code here that >> reads the amount of processor cores from `/proc/cpuinfo` (linux only I >> think) and some assembly code [asmmode att] (tested on x86_64 and i386) >> that *tries* to get the amount of cpu cores by the use of CPUID. The > In the general case, you have to be careful with this since (a) > every architecture puts different info in /proc/cpuinfo and (b) the > processor numbering and affinity vectors can have gaps. In the general case how is his x86 asm supposed to ever work on anything but Intel or AMD boxes?

It isn't, it will need to be rewritten. But that shouldn't be a problem since most cpu's will have instuctions for
- Add
- Compare
- Jump
- Shift
- Binary And
- CPUID (probably not under this name, but I beleive most modern CPU's have got some kind of equivalent)

The same thing goes for platform specific code by the way, you can't expect code that uses baseunix to compile without modification on a non unix box (e.g. windows).

Ewald

Reply by email

Ludo Brands
to Ewald: Hmmm, that's weird. The results of the Xeon are what I was expecting. Quite frankly I…
Ewald wrote 10 lines
Hmmm, that's weird. The results of the Xeon are what I was expecting. Quite frankly I don't know how to fix it. Maybe getting the maximum amount of threads sharing the caches might prove helpfull, but then again it is guesswork. Anyway, can you give this code a try? Than if I take the highest value from this and the previous program it *might* provide a sensible result. (?)

Xeon:#max threads sharing caches: 16
Atom:#max threads sharing caches: 2

On Xeon cpuid 00000004 returns 0x1c004121 in rax , on Atom 0x4121 in eax. So both report 2 threads per cache. The cores per package (bits 31..26) is not coherent. Don't know how to solve that.

Ludo

Reply by email

patspiper
to Ewald: Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said: Yeah, that could…
Ewald wrote 55 lines
Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said: > On 27/12/12 22:38, Ewald wrote: >> Hmmm, that;s indeed quite some different output you've got there. >> Mine looks like this: >> >> processor : 0 >> vendor_id : GenuineIntel >> cpu family : 6 >> model : 23 >> model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz >> stepping : 10 >> microcode : 0xa07 >> cpu MHz : 2000.000 >> cache size : 6144 KB >> physical id : 0 >> siblings : 2 >> core id : 0 >> cpu cores : 2 >> apicid : 0 >> initial apicid : 0 >> fpu : yes >> fpu_exception : yes >> cpuid level : 13 >> wp : yes >> flags : fpu vme de pse tsc msr pae mce cx8 apic sep >> mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 >> ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts >> rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est >> tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm tpr_shadow >> vnmi flexpriority >> bogomips : 6668.63 >> clflush size : 64 >> cache_alignment : 64 >> address sizes : 36 bits physical, 48 bits virtual >> power management: >> >> >> (this is repeated twice, with only `processor:0` changing to >> `processor:1`) >> >> >> Since this is the same kind of output I got on several other linux >> distributions/architectures(--> 32 bit versus 64 bit intel), I >> assumed it was kinda `standard`. Then again assume = ... >> >> Well, anyway, it's a bit trickier than I thought at first in that case. > > I guess one way of calculating the number of processors is to iterate > through every 'processor' in the list and add 1 if 'siblings' = 'cpu > cores' (no hyperthreading), and 0.5 if 'siblings' = 2 x 'cpu cores' > (hyperthreading enabled). Yeah, that could work, but then again the actual format of the data may be different measured over several distributions: suppose all `:` all of the sudden become `=`? Suppose that an identifier like `processor` undergoes a slicht namechange to `processorid`?

A workaround for this specific type of uncertainty can use a different logic: The count of distinct (physical id, core id) lines is the actual number of cores. That way = or : will not matter anymore. This excludes identifier changes of course.

As I said, I didn't know formats of /proc/cpuinfo differ over distributions/os'es, so it isn't safe to use this approach since all of the sudden a simly system update *might* just break your application.

True. A better bet would be to look for the code that produces the cpuinfo, and use that code directly.

Stephano

Reply by email

patspiper
to patspiper
patspiper wrote 66 lines
On 28/12/12 17:00, Ewald wrote: > Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said: >> On 27/12/12 22:38, Ewald wrote: >>> Hmmm, that;s indeed quite some different output you've got there. >>> Mine looks like this: >>> >>> processor : 0 >>> vendor_id : GenuineIntel >>> cpu family : 6 >>> model : 23 >>> model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz >>> stepping : 10 >>> microcode : 0xa07 >>> cpu MHz : 2000.000 >>> cache size : 6144 KB >>> physical id : 0 >>> siblings : 2 >>> core id : 0 >>> cpu cores : 2 >>> apicid : 0 >>> initial apicid : 0 >>> fpu : yes >>> fpu_exception : yes >>> cpuid level : 13 >>> wp : yes >>> flags : fpu vme de pse tsc msr pae mce cx8 apic sep >>> mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 >>> ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts >>> rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est >>> tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm tpr_shadow >>> vnmi flexpriority >>> bogomips : 6668.63 >>> clflush size : 64 >>> cache_alignment : 64 >>> address sizes : 36 bits physical, 48 bits virtual >>> power management: >>> >>> >>> (this is repeated twice, with only `processor:0` changing to >>> `processor:1`) >>> >>> >>> Since this is the same kind of output I got on several other linux >>> distributions/architectures(--> 32 bit versus 64 bit intel), I >>> assumed it was kinda `standard`. Then again assume = ... >>> >>> Well, anyway, it's a bit trickier than I thought at first in that case. >> >> I guess one way of calculating the number of processors is to >> iterate through every 'processor' in the list and add 1 if >> 'siblings' = 'cpu cores' (no hyperthreading), and 0.5 if 'siblings' >> = 2 x 'cpu cores' (hyperthreading enabled). > Yeah, that could work, but then again the actual format of the data > may be different measured over several distributions: suppose all `:` > all of the sudden become `=`? Suppose that an identifier like > `processor` undergoes a slicht namechange to `processorid`? A workaround for this specific type of uncertainty can use a different logic: The count of distinct (physical id, core id) lines is the actual number of cores. That way = or : will not matter anymore. This excludes identifier changes of course. > > As I said, I didn't know formats of /proc/cpuinfo differ over > distributions/os'es, so it isn't safe to use this approach since all > of the sudden a simly system update *might* just break your application. True. A better bet would be to look for the code that produces the cpuinfo, and use that code directly.

Try lscpu -p

Stephano

Reply by email

patspiper
to patspiper
patspiper wrote 69 lines
On 28/12/12 17:41, patspiper wrote: > On 28/12/12 17:00, Ewald wrote: >> Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said: >>> On 27/12/12 22:38, Ewald wrote: >>>> Hmmm, that;s indeed quite some different output you've got there. >>>> Mine looks like this: >>>> >>>> processor : 0 >>>> vendor_id : GenuineIntel >>>> cpu family : 6 >>>> model : 23 >>>> model name : Intel(R) Core(TM)2 Duo CPU E8600 @ 3.33GHz >>>> stepping : 10 >>>> microcode : 0xa07 >>>> cpu MHz : 2000.000 >>>> cache size : 6144 KB >>>> physical id : 0 >>>> siblings : 2 >>>> core id : 0 >>>> cpu cores : 2 >>>> apicid : 0 >>>> initial apicid : 0 >>>> fpu : yes >>>> fpu_exception : yes >>>> cpuid level : 13 >>>> wp : yes >>>> flags : fpu vme de pse tsc msr pae mce cx8 apic sep >>>> mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 >>>> ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts >>>> rep_good nopl aperfmperf pni dtes64 monitor ds_cpl vmx smx est >>>> tm2 ssse3 cx16 xtpr pdcm sse4_1 xsave lahf_lm dtherm >>>> tpr_shadow vnmi flexpriority >>>> bogomips : 6668.63 >>>> clflush size : 64 >>>> cache_alignment : 64 >>>> address sizes : 36 bits physical, 48 bits virtual >>>> power management: >>>> >>>> >>>> (this is repeated twice, with only `processor:0` changing to >>>> `processor:1`) >>>> >>>> >>>> Since this is the same kind of output I got on several other linux >>>> distributions/architectures(--> 32 bit versus 64 bit intel), I >>>> assumed it was kinda `standard`. Then again assume = ... >>>> >>>> Well, anyway, it's a bit trickier than I thought at first in that >>>> case. >>> >>> I guess one way of calculating the number of processors is to >>> iterate through every 'processor' in the list and add 1 if >>> 'siblings' = 'cpu cores' (no hyperthreading), and 0.5 if 'siblings' >>> = 2 x 'cpu cores' (hyperthreading enabled). >> Yeah, that could work, but then again the actual format of the data >> may be different measured over several distributions: suppose all >> `:` all of the sudden become `=`? Suppose that an identifier like >> `processor` undergoes a slicht namechange to `processorid`? > A workaround for this specific type of uncertainty can use a > different logic: The count of distinct (physical id, core id) lines > is the actual number of cores. That way = or : will not matter > anymore. This excludes identifier changes of course. >> >> As I said, I didn't know formats of /proc/cpuinfo differ over >> distributions/os'es, so it isn't safe to use this approach since all >> of the sudden a simly system update *might* just break your application. > True. A better bet would be to look for the code that produces the > cpuinfo, and use that code directly. Try lscpu -p

More options:
nproc (returns the number of processing units available whatever that means).
or use libcpuid (http://libcpuid.sourceforge.net/index.html)

Example (not tested):

#include <stdio.h>
#include <libcpuid.h>

int main(void)
{
if (!cpuid_present()) {

         printf("Sorry, your CPU doesn't support CPUID!\n");
         return -1;
     }
     struct cpu_raw_data_t raw;
     struct cpu_id_t data;
     if (cpuid_get_raw_data(&raw) < 0) {
         printf("Sorry, cannot get the CPUID raw data.\n");
         printf("Error: %s\n", cpuid_error());
         return -2;
     }
     if (cpu_identify(&raw, &data) < 0) {
         printf("Sorrry, CPU identification failed.\n");
         printf("Error: %s\n", cpuid_error());
         return -3;
     }
     printf("Processor has %d physical cores\n", data.num_cores);
     return 0;
}

Stephano

Reply by email

Marco van de Voort
to Mark Morgan Lloyd: If the number of CPUs changed during the lifetime of an app, it would need to know the…

In our previous episode, Mark Morgan Lloyd said:

Show quoted text 9 lines
> Note that in applications this should never be used for more than the > default of a configurable option anyway. > > The way new processors deal with this, can change at any time, and not > making this configurable would seriously limit the durability of the > software. If the number of CPUs changed during the lifetime of an app, it would need to know the current situation rather than the original one.

Or need to be restarted. But I think that is already several levels beyond something like a simple corecount, since that pretty much only signals a default for how many workerthreads can be started somewhat efficiently.

(and then you would prefer something event based rather than continues polling to see if the #cores changes)

HT cores shouldn't be included in that, since they mostly only improve thread latency. For the workerthreads metric, physical cores +1 is probably closer to an optimal situation than virtual cores on most processor.

Reply by email

Marco van de Voort
to Ewald: Once upon a time, on 12/28/2012 11:01 AM to be precise, patspiper said: Yeah, that could…

In our previous episode, Ewald said:

Show quoted text 6 lines
> cores' (no hyperthreading), and 0.5 if 'siblings' = 2 x 'cpu cores' > (hyperthreading enabled). Yeah, that could work, but then again the actual format of the data may be different measured over several distributions: suppose all `:` all of the sudden become `=`? Suppose that an identifier like `processor` undergoes a slicht namechange to `processorid`?

True. /proc is indeed not very desirable in general, and might vary per architecture too.

OTOH, even if CPUID works, and it is maintainable, it only is for one architecture, and in general in these cases the problem is getting it to work for the least popular targets/architectures, the most popular ones are usually easily implemented after a few googles, and also keeping them up to date is less of a problem.

Reply by email

Sven Barth
to Marco van de Voort: In our previous episode, Mark Morgan Lloyd said: Or need to be restarted. But I think…
Marco van de Voort wrote 21 lines
In our previous episode, Mark Morgan Lloyd said: >> Note that in applications this should never be used for more than the >> default of a configurable option anyway. >> >> The way new processors deal with this, can change at any time, and not >> making this configurable would seriously limit the durability of the >> software. > > If the number of CPUs changed during the lifetime of an app, it would > need to know the current situation rather than the original one. Or need to be restarted. But I think that is already several levels beyond something like a simple corecount, since that pretty much only signals a default for how many workerthreads can be started somewhat efficiently. (and then you would prefer something event based rather than continues polling to see if the #cores changes) HT cores shouldn't be included in that, since they mostly only improve thread latency. For the workerthreads metric, physical cores +1 is probably closer to an optimal situation than virtual cores on most processor.

CPUCount on Delphi does return the number of HT cores. E.g. "8" on an Intel i7 QuadCore processor.

Regards,
Sven

Reply by email

waldo kitty
to patspiper: Try lscpu -p Stephano
patspiper wrote 8 lines
On 28/12/12 17:41, patspiper wrote: > On 28/12/12 17:00, Ewald wrote: >> As I said, I didn't know formats of /proc/cpuinfo differ over >> distributions/os'es, so it isn't safe to use this approach since all of the >> sudden a simly system update *might* just break your application. > True. A better bet would be to look for the code that produces the cpuinfo, > and use that code directly. Try lscpu -p

FWIW: i wanted to try this on my ubuntu hardy 8.04.4 install but lscpu was not found so i spoke to uncle google and turned up the following post on another list... note the last sentence in the last paragraph ;)

[quote]
Re: [Trisquel-users] Is there a simple command to find out your architecture?

Michał Masłowski Mon, 20 Aug 2012 11:11:45 -0700

lscpu seems nice. Is it sufficient? Is it pre-installed with other free distros? It is included in util-linux package.

Outputs on an x86_64 machine with x86_64 Parabola, x86_64 virtual machine with i686 BLAG and mips64 machine with Parabola (mips64el) suggest it being ok (for x86_64 it will tell that there is a 64-bit "CPU op-mode", for most other architectures just the "Architecture" field obviously states what's needed).

Practically all non-embedded distros have util-linux, the 2.15-rc1 release is the first one including lscpu (easy to check using git). Not all free distros have it in the newest official stable release, gNewSense 2.3 probably has an older one since Ubuntu Hardy has (although it's easy to use uname -m and /proc/cpuinfo in such cases, like lscpu internally does).
[/quote]

Reply by email

Ewald
to patspiper: A workaround for this specific type of uncertainty can use a different logic: The count…

Once upon a time, on 12/28/2012 04:41 PM to be precise, patspiper said:

Show quoted text 6 lines
> > As I said, I didn't know formats of /proc/cpuinfo differ over > distributions/os'es, so it isn't safe to use this approach since all > of the sudden a simly system update *might* just break your application. True. A better bet would be to look for the code that produces the cpuinfo, and use that code directly.

Agreed.

Ewald

Reply by email

Ewald
to Ludo Brands: Xeon:#max threads sharing caches: 16 Atom:#max threads sharing caches: 2 On Xeon cpuid…

Once upon a time, on 12/28/2012 04:25 PM to be precise, Ludo Brands said:

Show quoted text 17 lines
On 28/12/2012 15:46, Ewald wrote: > Hmmm, that's weird. The results of the Xeon are what I was expecting. > > Quite frankly I don't know how to fix it. Maybe getting the maximum > amount of threads sharing the caches might prove helpfull, but then > again it is guesswork. Anyway, can you give this code a try? > > Than if I take the highest value from this and the previous program it > *might* provide a sensible result. (?) > > Xeon:#max threads sharing caches: 16 Atom:#max threads sharing caches: 2 On Xeon cpuid 00000004 returns 0x1c004121 in rax , on Atom 0x4121 in eax. So both report 2 threads per cache. The cores per package (bits 31..26) is not coherent. Don't know how to solve that.

Well, it is as you say, the `max cores per packge` just doesn't make any can a processor hav e a maximum of one core per
physical package, while in reality it has two threads sharing the same cache? Either I'm missing something here, or the behaviour of CPUID has changed over the years.

Either way: it leaves me with a method that is not 100% reliable.

Ewald

Reply by email

Ewald
to Marco van de Voort: In our previous episode, Ewald said: True. /proc is indeed not very desirable in general,…

Once upon a time, on 12/28/2012 05:59 PM to be precise, Marco van de Voort said:

Show quoted text 9 lines
In our previous episode, Ewald said: >> cores' (no hyperthreading), and 0.5 if 'siblings' = 2 x 'cpu cores' >> (hyperthreading enabled). > Yeah, that could work, but then again the actual format of the data may > be different measured over several distributions: suppose all `:` all of > the sudden become `=`? Suppose that an identifier like `processor` > undergoes a slicht namechange to `processorid`? True. /proc is indeed not very desirable in general, and might vary per architecture too.

Agreed.

Show quoted text 6 lines
OTOH, even if CPUID works, and it is maintainable, it only is for one architecture, and in general in these cases the problem is getting it to work for the least popular targets/architectures, the most popular ones are usually easily implemented after a few googles, and also keeping them up to date is less of a problem.

Yep, that's true, a few quick searches gives you something to get started. Then again I thought an cpu-specific implementation could also be quite handy since
- There are no external depencies
- It is OS independant

Now, since apparantly the CPUID function returns ambiguous results from time to time it obviously cannot be used in a usefull manner.

Ewald

Reply by email

Ludo Brands
to Ewald: Once upon a time, on 12/28/2012 04:25 PM to be precise, Ludo Brands said: Well, it is as…
Ewald wrote 12 lines
> Xeon:#max threads sharing caches: 16 > Atom:#max threads sharing caches: 2 > > On Xeon cpuid 00000004 returns 0x1c004121 in rax , on Atom 0x4121 in > eax. So both report 2 threads per cache. The cores per package (bits > 31..26) is not coherent. Don't know how to solve that. Well, it is as you say, the `max cores per packge` just doesn't make any can a processor hav e a maximum of one core per physical package, while in reality it has two threads sharing the same cache? Either I'm missing something here, or the behaviour of CPUID has changed over the years.

Atom 230 is one of the first atoms.
http://www.intel.com/content/www/us/en/processors/atom/atom-200-specification-update.html lists a few bugs with cpuid but not this one.

Either way: it leaves me with a method that is not 100% reliable.

This uses libc but on the Xeon and Atom it gives the correct result using debian and ubuntu:

program cpucount;
{$mode objfpc}{$H+}
function sysconf (__name : longint) : longint; cdecl; external 'c' name
'sysconf';
const
   _SC_UIO_MAXIOV = 60;
   _SC_NPROCESSORS_CONF = (_SC_UIO_MAXIOV)+23;
begin
   writeln('Number of processors: ',sysconf(_SC_NPROCESSORS_CONF));
end.

_SC_NPROCESSORS_CONF is defined in POSIX.2:
http://www.kernel.org/doc/man-pages/online/pages/man3/sysconf.3.html

Ludo

Reply by email

Ewald
to Ludo Brands: Atom 230 is one of the first atoms. http://www.intel.com/content/www/us/en/processors/atom…

Once upon a time, on 12/28/2012 08:27 PM to be precise, Ludo Brands said:

Show quoted text 9 lines
On 28/12/2012 20:01, Ewald wrote: > Well, it is as you say, the `max cores per packge` just doesn't make any > can a processor hav e a maximum of one core per > physical package, while in reality it has two threads sharing the same > cache? Either I'm missing something here, or the behaviour of CPUID has > changed over the years. Atom 230 is one of the first atoms. http://www.intel.com/content/www/us/en/processors/atom/atom-200-specification-update.html lists a few bugs with cpuid but not this one.

Well, maybe we have just uncovered another bug? ;-)

Show quoted text 21 lines
> Either way: it leaves me with a method that is not 100% reliable. This uses libc but on the Xeon and Atom it gives the correct result using debian and ubuntu: program cpucount; {$mode objfpc}{$H+} function sysconf (__name : longint) : longint; cdecl; external 'c' name 'sysconf'; const _SC_UIO_MAXIOV = 60; _SC_NPROCESSORS_CONF = (_SC_UIO_MAXIOV)+23; begin writeln('Number of processors: ',sysconf(_SC_NPROCESSORS_CONF)); end. _SC_NPROCESSORS_CONF is defined in POSIX.2: http://www.kernel.org/doc/man-pages/online/pages/man3/sysconf.3.html

Cool! And since it only depends on libc, it could be integrated nicely into cthreads for that matter :-)

Ewald

Reply by email

Ewald
to Marco van de Voort: In our previous episode, Sven Barth said: Then I really wonder what it is good for.

Once upon a time, on 12/28/2012 08:30 PM to be precise, Marco van de Voort said:

In our previous episode, Sven Barth said: > CPUCount on Delphi does return the number of HT cores. E.g. "8" on an > Intel i7 QuadCore processor. Then I really wonder what it is good for.

For giving the program(mer) an idea? As a default value for use in configfiles (e.g. `-1 cores` = autodetect)?

Ewald

Reply by email

Marco van de Voort
to Ewald

In our previous episode, Ewald said:

Show quoted text 5 lines
> In our previous episode, Sven Barth said: >> CPUCount on Delphi does return the number of HT cores. E.g. "8" on an >> Intel i7 QuadCore processor. > Then I really wonder what it is good for. For giving the program(mer) an idea?

"An idea" is IMHO not a wrong by a factor two :-)

If Intel ever goes to four fold SMT (like Sun did), it is even worse.

As a default value for use in configfiles (e.g. `-1 cores` = autodetect)?

That is what I thought originally too, but if two nearly the same machine (i5 and its corresponding i7) differ by a factor 2, IMHO it is useless, and wiser to default to 2 until the user adjusts it. (or 1 if you also target an audience with a lot of legacy machines)

Reply by email

Henry Vermaak
to Sven Barth: Hello Free Pascal community! I'm pleased to announce the extension of TThread's interface…
Sven Barth wrote 5 lines
- ProcessorCount (class): Returns the count of CPU cores detected by the RTL. This is based on the new global property System.GetCPUCount which needs to be implemented per target. Currently only a default implementation exists which returns "1".

On linux, this can be done with sched_getaffinity, which gives you the number of processing units that the current process can run on. I guess this is the number we're looking for here?

If you need all the processors, you need to read the information under /sys/devices/system/cpu (the topology subdirectory may be handy to filter out HTT), possibly falling back to /proc/stat and /proc/cpuinfo if necessary.

Take a look at the `nproc` utility from gnu coreutils.

http://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/nproc.c http://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getsysstats.c;h=22285f39f33bf26cd55f424ddf4f24300d0d9e72;hb=HEAD

Henry

Reply by email