Jump to content



Photo

_WinAPI_GetSystemInfo


  • Please log in to reply
82 replies to this topic

#1 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 07 March 2009 - 05:51 PM

_WinAPI_GetSystemInfo

Posted Image


I needed to get the # of Processors for another project I have, so I was looking into MSDN to find the 'right' way to do it. I've actually stumbled upon a few ways, two are easy - the Environment variable %NUMBER_OF_PROCESSORS%, and also the Registry keys under "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\" ('tip' has a nice simple function to get that info, _FasterCpuInfo()).

Anyway, this API call seemed like it would be the best source, but this doesn't report on Hyperthreading ('fake') processors that are considered by the Operating System as individual processors.

It turns out, the only 'easy' way to get Hyperthreading info is using the CPUID instruction, or to decipher the array returned by the 'GetLogicalProcessorInformation' API call - which only works with newer OS's. I have since written a function that was a port of Intel source code (mixed with Assembly) that actually worked on the processors we were able to test it on - but it's probably of limited use to most AutoIT programmers, so I'm not including it (for now)

*edit: Fixed a structure descriptor that now allows this function to work correctly in x64 code.
*edit 8/14/09: Fixed it to work correctly in 32-bit mode on an x64 O/S. (needs to call a different API function)

Get the code at my site


Ascend4nt's AutoIT Code License agreement:
While I provide this source code freely, if you do use the code in your projects, all I ask is that:
  • If you provide source, keep the header as I have put it, OR, if you expand it, then at least acknowledge me as the original author, and any other authors I credit
  • If the program is released, acknowledge me in your credits (it doesn't have to state which functions came from me, though again if the source is provided - see #1)
  • The source on it's own (as opposed to part of a project) can not be posted unless a link to the page(s) where the code were retrieved from is provided and a message stating that the latest updates will be available on the page(s) linked to.
  • Pieces of the code can however be discussed on the threads where Ascend4nt has posted the code without worrying about further linking.

Edited by Ascend4nt, 14 September 2011 - 02:47 AM.






#2 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 02 July 2009 - 02:41 PM

Ascend4nt, a really nice script, thanks a lot for this one ;) ! Saw it already some weeks ago, but remembered it when I stumbled across something else...

I'm not quiet sure about this :) , but I think the return value 'lpSystemAffinityMask' of the GetProcessAffinityMask() function (as a bit vector) should match the number of logical processors... well, according to the docs at least for systems with a total of less than 64 processors :) ...
('active logical processors...a process affinity mask is a bit vector in which each bit represents the processors that a process is allowed to run on')
#include <WinAPI.au3> ; GetProcessAffinityMask() ; <a href='http://msdn.microsoft.com/en-us/library/ms683213(VS.85' class='bbc_url' title='External link' rel='norewrite nofollow external'>http://msdn.microsoft.com/en-us/library/ms683213(VS.85</a>).aspx Global Const $PROCESS_ALL_ACCESS = 0x1F0FFF $hProc = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, @AutoItPID) $aRet = _WinAPI_GetProcessAffinityMask($hProc) MsgBox(0, "", "Success = " & $aRet[0] & @LF & _               "lpProcessAffinityMask = " & $aRet[1] & @LF & _               "lpSystemAffinityMask = " & $aRet[2] & @LF & @LF & _               "# of logical processors = " & Sqrt($aRet[2]+1))

Edited by KaFu, 02 July 2009 - 02:55 PM.


#3 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 02 July 2009 - 11:53 PM

Kafu, just tried your script - and it returned 4 logical processors. (I have 4 cores, no hyperthreading, so.. ernnhh!! fail!) Sorry! hehe

But you inspired me to try out the 'GetLogicalProcessorInformation' API function (available for O/S's with XP SP3, XP x64, or Server 2003 and above)

What I got, after figuring out the structures and creating a loop to go through them, was the below confusing mess. I can probably ignore the 'Cache' structure info, but how I can determine what logical processors exist, I don't know yet. I'd probably have to send the program I wrote to someone who has Hyperthreading or 'Logical cores'...

One of the problems with this Windows API call is that, not only does it have the above O/S requirements, some of the return values have *further* O/S requirements. Argh, frustrating..

Plain Text         
Window's GetLogicalProcessorInformation call Results: Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #1 Processor Mask:00000001, Relationship:RelationProcessorCore Processor Core Flags:0 ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #2 Processor Mask:00000001, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheData ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #3 Processor Mask:00000001, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheInstruction ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #4 Processor Mask:00000002, Relationship:RelationProcessorCore Processor Core Flags:0 ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #5 Processor Mask:00000002, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheData ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #6 Processor Mask:00000002, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheInstruction ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #7 Processor Mask:00000003, Relationship:RelationCache Cache Descriptor fields:     Level:2, Associativity:16, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:4194304, Cache type:CacheUnified ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #8 Processor Mask:00000004, Relationship:RelationProcessorCore Processor Core Flags:0 ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #9 Processor Mask:00000004, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheData ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #10 Processor Mask:00000004, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheInstruction ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #11 Processor Mask:0000000F, Relationship:RelationProcessorPackage ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #12 Processor Mask:00000008, Relationship:RelationProcessorCore Processor Core Flags:0 ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #13 Processor Mask:00000008, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheData ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #14 Processor Mask:00000008, Relationship:RelationCache Cache Descriptor fields:     Level:1, Associativity:8, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:32768, Cache type:CacheInstruction ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #15 Processor Mask:0000000C, Relationship:RelationCache Cache Descriptor fields:     Level:2, Associativity:16, (Cache) Line Size, in bytes:64, (Cache) Size, in bytes:4194304, Cache type:CacheUnified ------------------------------------------------------------- Processor Information for SYSTEM_LOGICAL_PROCESSOR_INFORMATION, structure #16 Processor Mask:0000000F, Relationship:RelationNumaNode NumaNode Node Number:0


#4 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 02:16 AM

I have a dual core laptop, no hyperthreading, and msinfo32 says 2 cores, 2 logical processors. So isn't 4 the right answer for your quad core machine?

#5 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 03 July 2009 - 02:20 AM

Well what we are looking for is Logical vs. Actual. Basically, we want to find out which are the Logical/Hyperthreading cores and separate those from the Actual cores, so that we have two counts. For me the 'pretend' cores would be 0..

*edit: maybe I misread what Kafu was trying to communicate? The whole 'logical' business gets confusing here. Anyway, wraithdu, if you could run his program and let me know what it gives you as a result? I could also send you a quick program that gives you output (in and edit box) similar to what I posted above.

Edited by ascendant, 03 July 2009 - 02:24 AM.


#6 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 02:29 AM

I think in a multi-core non-hyperthreading system the number of physical and logical processors is the same. Check out the utility on this page and see what your results are -

http://www.codeproject.com/KB/system/countingprocessors.aspx

EDIT -
I ran Kafu's program and it returns 2. His script is going to always count logical processors, which should be >= the number of physical processors.

Edited by wraithdu, 03 July 2009 - 02:30 AM.


#7 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 03 July 2009 - 02:40 AM

Oops, for some reason I thought you had hyperthreading. haha, I'm misreading a bit today.

Anyway, as expected, that utility reports

CPU Counting Utility
Hyper-threading technology not capable
Number of logical processors per physical processor: 1
Number of physical processors: 4
Press Enter To Continue


If that reported something like '2 logical processors per physical processor', THEN we'd be able to see how many hmm.. need a better term... 'non-physical processors' existed. Hopefully you get what I mean.

Anyway, the CPUID instruction is the only universal way to get the correct information, but it requires Assembly language code. GetLogicalProcessorInformation should report the right information too, but at the moment I don't know how to interpret it (plus we have O/S limitations).

#8 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 03:40 AM

Right, so Kafu's script is correct on your system - 4 physical processors X 1 logical processor for each physical = 4 logical processors.

#9 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 03 July 2009 - 03:58 AM

Kafu's script, unless proven otherwise, is the same as _WinAPI_GetSystemInfo() and the variants listed within for getting 'logical' processor counts.

But as I've been trying to say, it's not a way to get a physical processor count - unless, like in mine and your cases, it actually matches. But the code doesn't know that, and that's what we're after - something that runs and detects physical processors vs logical processors. (For example, if I had Hyperthreading available on each core, that would be 4 vs. 8)

#10 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 05:36 AM

Oh, I thought from your first post you had the physical processors part covered and were just looking for a way to get the logical processors.

From what I'm reading in GetSystemInfo(), it returns the physical processor count, not logical processors. My computer at work is a single core with hyperthreading. It should be a good test for this. I can try this out on Monday.

#11 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 03 July 2009 - 05:45 AM

For me the 'pretend' cores would be 0

Just woke up :) ... so, maybe you mean something like

'pretended' cores = Sqrt($aRet[2]+1) from _WinAPI_GetProcessAffinityMask() minus aSysInfo[5] from _WinAPI_GetSystemInfo() :) ?

AutoIt         
#include <WinAPI.au3> $aSysInfo = _WinAPI_GetSystemInfo() ; GetProcessAffinityMask() ; http://msdn.microsoft.com/en-us/library/ms683213(VS.85).aspx Global Const $PROCESS_ALL_ACCESS = 0x1F0FFF $hProc = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, @AutoItPID) $aRet = _WinAPI_GetProcessAffinityMask($hProc) MsgBox(0, "", "Physical processor count: " & @tab & $aSysInfo[5] & @LF & _               "Logical processor count: " & @tab & Sqrt($aRet[2]+1) & @LF & _               "Virtual processor count: " & @tab & Sqrt($aRet[2]+1) - $aSysInfo[5]) ; =================================================================================================== ; Func _WinAPI_GetSystemInfo($iInformation=-1) ; ; Retrieves an array of system information, or just one item based on parameter ; ; $iInformation = The piece of information you would like to collect, or -1 for an entire array: ;   1 = Processor Architecture [0 = Intel, 6 = Itanium64, 9 = x64 (AMD or Intel), 0xFFFF = Unknown] ;   2 = Page Size (don't know yet?) ;   3 = Minimum Application Address ;   4 = Maximum Application Address ;   5 = Active Processor Mask - Set Bits indicate processor has been 'configured into the system' (MSDN) ;       [Bit 0 = processor # 0, Bit 31 = processor 31 ;   6 = Number of Processors [not the same as 'Logical Processors'] ;   7 = Processor Type [386 = Intel 386, 486 = "" 486, 586 = Pentium, 2200 = Itanium64, 8664 = AMD x8664 (?) ;   8 = Allocation Granularity ("granularity for the starting address at which virtual memory can be allocated" - MSDN) ;   9 = Processor Level (1 for Itanium64, otherwise for Processor Architecture 0 it represents CPU-vendor-specific info) ;   10 = Processor Revision (no clue - check out http://msdn.microsoft.com/en-us/library/ms...58(VS.85).aspx) ; ; Return: ;   Success: @error=0, and either a 10-element array filled in the order described above #1 at element [0], #10 at [9], ;       or a # associated with $iInformation ;   Failure: -1 return, @error is set: ;       @error = 1 = invalid parameter (out of range) ;       @error = 2 = DLL call error ; ; Other WinAPI calls to get Processor Info: ;   GetLogicalProcessorInformation  [unfortunately available only on Win XP w/SP3 and higher] ;   IsProcessorFeaturePresent (get processor features information) ; ; Other ways to obtain Processor Information: ;   %NUMBER_OF_PROCESSORS%  Environment variable: Number of Processors (physical, not logical, again) ;       EnvGet("NUMBER_OF_PROCESSORS") ; ;   "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\" ;       [one subkey for each physical processor, and inside the 1st key (and some inside subsequent ones is)]: ;           Speed, Features set, Processor Name, Identifier, etc. ; ; Author: Ascend4nt ; =================================================================================================== Func _WinAPI_GetSystemInfo($iInformation=-1)     If $iInformation<>-1 And ($iInformation<1 Or $iInformation>10) Then Return SetError(1,0,-1)     Local $aRet,$stSystemInfo=DllStructCreate("ushort;short;dword;ptr;ptr;dword;dword;dword;dword;short;short")     $aRet=DllCall("kernel32.dll","none","GetSystemInfo","ptr",DllStructGetPtr($stSystemInfo))     If @error Or Not IsArray($aRet) Then Return SetError(2,0,-1)     If $iInformation<>-1 Then         If $iInformation==1 Then Return DllStructGetData($stSystemInfo,1)         Return DllStructGetData($stSystemInfo,$iInformation+1)     EndIf     Local $aSysInfo[10]     $aSysInfo[0]=DllStructGetData($stSystemInfo,1)     For $i=1 To 9         $aSysInfo[$i]=DllStructGetData($stSystemInfo,$i+2)     Next     #cs     ; Full feature display:     MsgBox(64,"System Info", _         "Processor Architecture:"&$aSysInfo[0]&@CRLF& _         "Page Size:"&$aSysInfo[1]&@CRLF& _         "Minimum Application Address:"&$aSysInfo[2]&@CRLF& _         "Maximum Application Address:"&$aSysInfo[3]&@CRLF& _         "Active Processor Mask:"&Hex($aSysInfo[4])&@CRLF& _         "Number of Processors:"&$aSysInfo[5]&@CRLF& _         "Processor Type:"&$aSysInfo[6]&@CRLF& _         "Allocation Granularity:"&$aSysInfo[7]&@CRLF& _         "Processor Level:"&Hex($aSysInfo[8])&@CRLF& _         "Processor Revision:"&Hex($aSysInfo[9]))     #ce     Return $aSysInfo EndFunc

Edit: Returns 4,4,0 to me on homebox... Quad core without HT, and 2,2,0 on Notebook, Dual Core without HT, so that should be okay.

Edited by KaFu, 03 July 2009 - 06:55 AM.


#12 bo8ster

bo8ster

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,189 posts

Posted 03 July 2009 - 05:47 AM

Not a bad tool, thanks ascendant.
Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)Brett F's Learning To Script with AutoIt V3Valuater's AutoIt 1-2-3, Class... is now in SessionContribution: Get SVN Rev Number, Control Handle under mouse, A Presentation using AutoIt, Log ConsoleWrite output in Scite

#13 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 03 July 2009 - 07:42 AM

Just woke up :) ... so, maybe you mean something like

'pretended' cores = Sqrt($aRet[2]+1) from _WinAPI_GetProcessAffinityMask() minus aSysInfo[5] from _WinAPI_GetSystemInfo() ;) ?

Edit: Returns 4,4,0 to me on homebox... Quad core without HT, and 2,2,0 on Notebook, Dual Core without HT, so that should be okay.

KaFu, the whole Sqrt thing confuses me.. not even sure what that's about? I thought the Mask was a bit set for each processor? *shrug* :)

#14 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 03 July 2009 - 08:07 AM

KaFu, the whole Sqrt thing confuses me.. not even sure what that's about? I thought the Mask was a bit set for each processor? *shrug* :)

Yep, 1 processor = 1, 2 processors = 1+2, 3 processors = 1+2+4, 4 processors = 1+2+4+8. And as this mask returns processor count, each bit to the last has to be one (at least I assume :) ).
E.g. for 4 processors the bitmask is 1111 => 4^2-1 = 15, thus the revision is 4 = Sqrt(15+1)... and yes, I had to think hard about the formulas too ;) , had my last mathematics course just too long ago.

Edited by KaFu, 03 July 2009 - 09:01 AM.


#15 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 04:52 PM

You're formula's not quite there:

binary 1: Sqrt(1+1) = 1.414
binary 11111: Sqrt(31 + 1) = 5.656
binary 1111111: Sqrt(127 + 1) = 11.313

I'm still trying to come up with something better. Need a formula to determine how many bits it takes to store a number.

Edited by wraithdu, 03 July 2009 - 04:52 PM.


#16 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 04:56 PM

Got it. We need to solve for x in: 2^x = $aRet[2] + 1, where $aRet[2] + 1 is the next bit in the bit vector, since for example the 4th bit has exponent 3 (2^3 = 8). So for a 4 bit vector, the next bit is 16 = 2^4 which is our 4 processors.

processors = Log($aRet[2] + 1) / Log(2)

Edited by wraithdu, 03 July 2009 - 05:00 PM.


#17 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 03 July 2009 - 05:11 PM

processors = Log($aRet[2] + 1) / Log(2)

Nice ;) , you're right... said my last math course was too long ago :) , just tested for 2 and 4 :)
$i = 1 ConsoleWrite("Sqrt " & Sqrt($i+1) & @CRLF) ConsoleWrite("Log " & Log($i + 1) / Log(2) & @crlf) $i = 3 ConsoleWrite("Sqrt " & Sqrt($i+1) & @CRLF) ConsoleWrite("Log " & Log($i + 1) / Log(2) & @crlf) $i = 7 ConsoleWrite("Sqrt " & Sqrt($i+1) & @CRLF) ConsoleWrite("Log " & Log($i + 1) / Log(2) & @crlf) $i = 15 ConsoleWrite("Sqrt " & Sqrt($i+1) & @CRLF) ConsoleWrite("Log " & Log($i + 1) / Log(2) & @crlf) $i = 31 ConsoleWrite("Sqrt " & Sqrt($i+1) & @CRLF) ConsoleWrite("Log " & Log($i + 1) / Log(2) & @crlf)

And heres an update of the functions...

AutoIt         
#include <WinAPI.au3> $aSysInfo = _WinAPI_GetSystemInfo() ; GetProcessAffinityMask() ; http://msdn.microsoft.com/en-us/library/ms683213(VS.85).aspx Global Const $PROCESS_ALL_ACCESS = 0x1F0FFF $hProc = _WinAPI_OpenProcess($PROCESS_ALL_ACCESS, False, @AutoItPID) $aRet = _WinAPI_GetProcessAffinityMask($hProc) MsgBox(0, "", "Physical processor count: " & @tab & $aSysInfo[5] & @LF & _               "Logical processor count: " & @tab & (Log($aRet[2] + 1) / Log(2)) & @LF & _               "Virtual processor count: " & @tab & (Log($aRet[2] + 1) / Log(2)) - $aSysInfo[5]) ; =================================================================================================== ; Func _WinAPI_GetSystemInfo($iInformation=-1) ; ; Retrieves an array of system information, or just one item based on parameter ; ; $iInformation = The piece of information you would like to collect, or -1 for an entire array: ;   1 = Processor Architecture [0 = Intel, 6 = Itanium64, 9 = x64 (AMD or Intel), 0xFFFF = Unknown] ;   2 = Page Size (don't know yet?) ;   3 = Minimum Application Address ;   4 = Maximum Application Address ;   5 = Active Processor Mask - Set Bits indicate processor has been 'configured into the system' (MSDN) ;       [Bit 0 = processor # 0, Bit 31 = processor 31 ;   6 = Number of Processors [not the same as 'Logical Processors'] ;   7 = Processor Type [386 = Intel 386, 486 = "" 486, 586 = Pentium, 2200 = Itanium64, 8664 = AMD x8664 (?) ;   8 = Allocation Granularity ("granularity for the starting address at which virtual memory can be allocated" - MSDN) ;   9 = Processor Level (1 for Itanium64, otherwise for Processor Architecture 0 it represents CPU-vendor-specific info) ;   10 = Processor Revision (no clue - check out http://msdn.microsoft.com/en-us/library/ms...58(VS.85).aspx) ; ; Return: ;   Success: @error=0, and either a 10-element array filled in the order described above #1 at element [0], #10 at [9], ;       or a # associated with $iInformation ;   Failure: -1 return, @error is set: ;       @error = 1 = invalid parameter (out of range) ;       @error = 2 = DLL call error ; ; Other WinAPI calls to get Processor Info: ;   GetLogicalProcessorInformation  [unfortunately available only on Win XP w/SP3 and higher] ;   IsProcessorFeaturePresent (get processor features information) ; ; Other ways to obtain Processor Information: ;   %NUMBER_OF_PROCESSORS%  Environment variable: Number of Processors (physical, not logical, again) ;       EnvGet("NUMBER_OF_PROCESSORS") ; ;   "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\" ;       [one subkey for each physical processor, and inside the 1st key (and some inside subsequent ones is)]: ;           Speed, Features set, Processor Name, Identifier, etc. ; ; Author: Ascend4nt ; =================================================================================================== Func _WinAPI_GetSystemInfo($iInformation=-1)     If $iInformation<>-1 And ($iInformation<1 Or $iInformation>10) Then Return SetError(1,0,-1)     Local $aRet,$stSystemInfo=DllStructCreate("ushort;short;dword;ptr;ptr;dword;dword;dword;dword;short;short")     $aRet=DllCall("kernel32.dll","none","GetSystemInfo","ptr",DllStructGetPtr($stSystemInfo))     If @error Or Not IsArray($aRet) Then Return SetError(2,0,-1)     If $iInformation<>-1 Then         If $iInformation==1 Then Return DllStructGetData($stSystemInfo,1)         Return DllStructGetData($stSystemInfo,$iInformation+1)     EndIf     Local $aSysInfo[10]     $aSysInfo[0]=DllStructGetData($stSystemInfo,1)     For $i=1 To 9         $aSysInfo[$i]=DllStructGetData($stSystemInfo,$i+2)     Next     #cs     ; Full feature display:     MsgBox(64,"System Info", _         "Processor Architecture:"&$aSysInfo[0]&@CRLF& _         "Page Size:"&$aSysInfo[1]&@CRLF& _         "Minimum Application Address:"&$aSysInfo[2]&@CRLF& _         "Maximum Application Address:"&$aSysInfo[3]&@CRLF& _         "Active Processor Mask:"&Hex($aSysInfo[4])&@CRLF& _         "Number of Processors:"&$aSysInfo[5]&@CRLF& _         "Processor Type:"&$aSysInfo[6]&@CRLF& _         "Allocation Granularity:"&$aSysInfo[7]&@CRLF& _         "Processor Level:"&Hex($aSysInfo[8])&@CRLF& _         "Processor Revision:"&Hex($aSysInfo[9]))     #ce     Return $aSysInfo EndFunc


#18 wraithdu

wraithdu

    I am less fun than a twisted ankle.

  • MVPs
  • 2,137 posts

Posted 03 July 2009 - 05:37 PM

Here's another interesting bit to get the number of active processors in the affinity mask. This would work up to 32 processors, since the AutoIt bit functions only work on 32-bit numbers.
$mask = 127 $nProcs = 0 For $i = 1 To 32     If BitAND($mask, 2^($i-1)) Then $nProcs += 1 Next ConsoleWrite("# of active processors:  " & $nProcs & @CRLF)


#19 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,162 posts

Posted 03 July 2009 - 05:58 PM

Or, assuming there are not gaps in the $aMask[2] - System affinity mask (as opposed to the $aMask[1] - Process affinity mask, where gaps indicate that a process should not run on that core) :) ...
$mask = 127 $nProcs = 0 For $i = 1 To 32     If BitAND($mask, 2^($i-1)) Then $nProcs = $i Next ConsoleWrite("# of logical processors:  " & $nProcs & @CRLF)

Edited by KaFu, 03 July 2009 - 06:01 PM.


#20 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,073 posts

Posted 03 July 2009 - 05:59 PM

Ahh, I get what you guys are doing.. hey, here's another way to get the processor count, similar to wraithdu's

    Local $iTotalCPUs=0    ; Remove topbit, otherwise the function will enter an endless loop     Local $iUnsignedNumber=BitAND($iProcessorNumber,0x7FFFFFFF)        ; Cycle through each bit, shifting to the right until 0     Do         $iTotalCPUs+=BitAND($iUnsignedNumber,1)         $iUnsignedNumber=BitShift($iUnsignedNumber,1)     Until Not $iUnsignedNumber


I still don't think you'll see a difference for Hyperthreaded CPUs though - I believe its treated for nearly every API call, registry entry, and environment variable as one value and its not distinguished...




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users