CPU Usage Multi-core

Just starting out? Need help? Post your questions and find answers here.
Gillou
New User
New User
Posts: 2
Joined: Fri Jun 16, 2006 3:31 pm
Location: France, Brittany, 22

CPU Usage Multi-core

Post by Gillou »

Hello all,

In advance, sorry for my bad english... ;)

I write this program to create a CPU Monitor... But after many test with french purebasic community, it's appears that this code doesn't work with quad core. We can see that the result like this :

CPU0 : 210%
CPU1 : 222%
CPU2 : 254%
CPU3 : 228%
CPU TOTAL : 228%

If anyone have an idea on this problem, that will be very good.

Thanks by advance for your interest.


CPU Usage code
Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    DpcTime.q
    InterruptTime.q
    InterruptCount.q
EndStructure

#MaxCpus = 32

#SystemProcessorPerformanceInformation = 8
#SysProcPerfInfoLength = 48

#PROCESS_QUERY_INFORMATION = $400
#HUNDRED_NANOSEC = 10000000

Declare.l cpu_count()

Global Frequency.q, TimeStart.q

Global NumberOfProcessors = cpu_count()

Global Dim CpuInfo.SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION(NumberOfProcessors)

Global Dim KernelTimesStart.d(NumberOfProcessors+1)
Global Dim UserTimesStart.d(NumberOfProcessors+1)
Global Dim IdleTimesStart.d(NumberOfProcessors+1)
Global Dim DpcTimesStart.d(NumberOfProcessors+1)
Global Dim InterruptTimesStart.d(NumberOfProcessors+1)

Global Dim KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.d(NumberOfProcessors+1)
Global Dim DpcTimesStop.d(NumberOfProcessors+1)
Global Dim InterruptTimesStop.d(NumberOfProcessors+1)

Global Dim KernelTimesDelta.d(NumberOfProcessors+1)
Global Dim UserTimesDelta.d(NumberOfProcessors+1)
Global Dim IdleTimesDelta.d(NumberOfProcessors+1)

Global Dim CpuUsages.d(NumberOfProcessors+1)

Procedure.l cpu_count() ; Number of processors or cores
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure

Procedure.s TimeConvert(time.q)
    hr.l = Round (time/36000000000, 0)
    time = time-(hr*36000000000)
    min.l = Round (time/600000000, 0)
    time = time-(min*600000000)
    sec.l = Round (time/10000000, 0)
    time = time-(sec*10000000)
    ms.l = Round (time/10000, 0)
     ProcedureReturn Str (hr)+ ":" + RSet ( Str (min), 2, "0" )+ ":" + RSet ( Str (sec), 2, "0" )+ ":" + RSet ( Str (ms), 3, "0" )
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
        Function = GetFunction (Lib, "NtQuerySystemInformation" )
         If CallFunctionFast (Function, #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * #MaxCpus , @ret) = 0
             If ret/ #SysProcPerfInfoLength = NumberOfProcessors
                 If start = #True
                    KernelTimesStart(NumberOfProcessors) = 0
                    IdleTimesStart(NumberOfProcessors) = 0
                    UserTimesStart(NumberOfProcessors) = 0
                    DpcTimesStart(NumberOfProcessors) = 0
                    InterruptTimesStart(NumberOfProcessors) = 0
                     For i = 0 To NumberOfProcessors - 1
                        KernelTimesStart(i) = CpuInfo(i)\KernelTime
                        IdleTimesStart(i) = CpuInfo(i)\IdleTime
                        UserTimesStart(i) = CpuInfo(i)\UserTime
                        DpcTimesStart(i) = CpuInfo(i)\DpcTime
                        InterruptTimesStart(i) = CpuInfo(i)\InterruptTime
                        KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + CpuInfo(i)\KernelTime
                        IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + CpuInfo(i)\IdleTime
                        UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + CpuInfo(i)\UserTime
                        DpcTimesStart(NumberOfProcessors) = DpcTimesStart(NumberOfProcessors) + CpuInfo(i)\DpcTime
                        InterruptTimesStart(NumberOfProcessors) = InterruptTimesStart(NumberOfProcessors) + CpuInfo(i)\InterruptTime
                     Next
                 Else
                    KernelTimesStop(NumberOfProcessors) = 0
                    IdleTimesStop(NumberOfProcessors) = 0
                    UserTimesStop(NumberOfProcessors) = 0
                    DpcTimesStop(NumberOfProcessors) = 0
                    InterruptTimesStop(NumberOfProcessors) = 0
                     For i = 0 To NumberOfProcessors - 1
                        KernelTimesStop(i) = CpuInfo(i)\KernelTime
                        IdleTimesStop(i) = CpuInfo(i)\IdleTime
                        UserTimesStop(i) = CpuInfo(i)\UserTime
                        DpcTimesStop(i) = CpuInfo(i)\DpcTime
                        InterruptTimesStop(i) = CpuInfo(i)\InterruptTime
                        KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + CpuInfo(i)\KernelTime
                        IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) + CpuInfo(i)\IdleTime
                        UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + CpuInfo(i)\UserTime
                        DpcTimesStop(NumberOfProcessors) = DpcTimesStop(NumberOfProcessors) + CpuInfo(i)\DpcTime
                        InterruptTimesStop(NumberOfProcessors) = InterruptTimesStop(NumberOfProcessors) + CpuInfo(i)\InterruptTime
                     Next
                 EndIf
             EndIf
         EndIf
         CloseLibrary (Lib)
     EndIf
EndProcedure

Procedure refresh()
    Protected CpuTime.d, CurTime.q, DiffTime.d
    
     QueryPerformanceCounter_ (@CurTime)
    GetProcessorsTimes( #False )
    CpuUsages(NumberOfProcessors) = 0
    
     For i = 0 To NumberOfProcessors - 1
        KernelTimesDelta(i) = KernelTimesStop(i) - KernelTimesStart(i)
        UserTimesDelta(i) = UserTimesStop(i) - UserTimesStart(i)
        IdleTimesDelta(i) = IdleTimesStop(i) - IdleTimesStart(i)
        CpuTime = (KernelTimesDelta(i) + UserTimesDelta(i) + IdleTimesDelta(i))
        DiffTime = (CurTime - TimeStart) / Frequency
         If DiffTime > 0 : CpuTime = ((CpuTime) / (DiffTime)) / NumberOfProcessors : EndIf
        CpuUsages(i) = (100 * (1 - CpuTime / #HUNDRED_NANOSEC ))
         If NumberOfProcessors = 1 : CpuUsages(i) = 100 + CpuUsages(i) : EndIf
         If CpuUsages(i) < 0 : CpuUsages(i) = 0 : EndIf
         ; If CpuUsages(i) > (100/NumberOfProcessors) : CpuUsages(i) = (100/NumberOfProcessors) : EndIf
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 2) ; Show percentage before adjusting to 100%
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
        DpcTimesStart(i) = DpcTimesStop(i)
        InterruptTimesStart(i) = InterruptTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, TimeConvert(KernelTimesStart(i)), 3)
         SetGadgetItemText (1, i, TimeConvert(UserTimesStart(i)), 4)
         SetGadgetItemText (1, i, TimeConvert(IdleTimesStart(i)), 5)
         SetGadgetItemText (1, i, TimeConvert(DpcTimesStart(i)), 6)
         SetGadgetItemText (1, i, TimeConvert(InterruptTimesStart(i)), 7)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(KernelTimesStart(NumberOfProcessors)), 3)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(UserTimesStart(NumberOfProcessors)), 4)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(IdleTimesStart(NumberOfProcessors)), 5)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(DpcTimesStart(NumberOfProcessors)), 6)
     SetGadgetItemText (1, NumberOfProcessors, TimeConvert(InterruptTimesStart(NumberOfProcessors)), 7)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 635, 140, "CPU Usage Multi-Processors" , #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If IsWindow (Win) And CreateGadgetList ( WindowID (Win))
     ListIconGadget (1, 10, 10, 615, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "% (" + Str (100/NumberOfProcessors)+ ")" , 60)
     AddGadgetColumn (1, 3, "Kernel Time" , 80)
     AddGadgetColumn (1, 4, "User Time" , 80)
     AddGadgetColumn (1, 5, "Idle Time" , 80)
     AddGadgetColumn (1, 6, "Dpc Time" , 80)
     AddGadgetColumn (1, 7, "Interrupt Time" , 80)
    
     For i=0 To NumberOfProcessors-1
         AddGadgetItem (1, -1, "CPU " + Str (i))
     Next
     AddGadgetItem (1, NumberOfProcessors, "CPU TOTAL" )
    
     SetTimer_ ( WindowID (Win), 1, 1000, @refresh())
     Repeat
         Select WaitWindowEvent ()
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf



Test code to change the processor's affinity
Declare set_affinity(CPU)
Declare cpu_count()

; Open the Task Manager
Shell_TrayWnd = FindWindow_ ( "Shell_TrayWnd" , NULL)
Result = SendMessage_ (Shell_TrayWnd, $111, 420, 0)

; Return name of process in task manager
ExeName.s = Space (255) : GetModuleFileName_ (0, @ExeName, 255)

Win = OpenWindow ( #PB_Any , 0, 0, 400, 200, "Multi-Core Test - " + GetFilePart (ExeName), #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_MinimizeGadget )
If Win And CreateGadgetList ( WindowID (Win))
     TextGadget ( #PB_Any , 10, 10, 180, 20, "Number of processors : " + Str (cpu_count()))
    CPU = 0
     For X = 0 To cpu_count()-1
         CheckBoxGadget (X, 10, (X*25)+30, 180, 20, "CPU " + Str (X))
        CPU + Pow (2, X)
         SetGadgetState (X, 1)
     Next
    set_affinity(CPU)
     Repeat
         Select WindowEvent () ; Just to use processors for multi-core test with WindowEvent
             Case #PB_Event_Gadget
                Event = EventGadget ()
                CPU = 0
                 For X = 0 To cpu_count()-1
                     If GetGadgetState (X) = 1
                        CPU + Pow (2, X)
                     EndIf
                 Next
                 If CPU = 0
                    set_affinity(1)
                     SetGadgetState (0, 1)
                 Else
                    set_affinity(CPU)
                 EndIf
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
EndIf

ProcedureDLL.l cpu_count() ; Number of processors or cores
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure
 
Procedure get_affinity(mode = 0) ; Mode = 0 : Process, Mode = 1 : System
    Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
    
    hProcess = GetCurrentProcess_ ()
     GetProcessAffinityMask_ (hProcess,@lpProcessAffinityMask,@lpSystemAffinityMask)
     If mode = 0
         ProcedureReturn lpProcessAffinityMask
     Else
         ProcedureReturn lpSystemAffinityMask
     EndIf
EndProcedure

Procedure set_affinity(CPU)
    Protected lpProcessAffinityMask.l, lpSystemAffinityMask.l, hProcess.l
    
    hProcess = GetCurrentProcess_ ()
    succes = SetProcessAffinityMask_ (hProcess, CPU)
    
     ProcedureReturn succes
EndProcedure
Gillou
New User
New User
Posts: 2
Joined: Fri Jun 16, 2006 3:31 pm
Location: France, Brittany, 22

Post by Gillou »

No idea?

If you know website where i can find information on CPU Usage on quad core or if you have an idea by other way to get the CPU Usage that will be great ;)
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Post by Helle »

The PDH.DLL ("Performance Data Helper") is in \System32 since W2k. This is a Code with this (in German, sorry):

Code: Select all

;- CPU-Auslastung-Ermittlung mit der PDH.DLL, auch für Multi-Core-CPU´s 
;- W2k, WXP, Vista(?) 
;- "Helle" Klaus Helbing, 22.03.2008, PB4.10 
;- Soll nur schmucklos die einfache Machbarkeit zeigen! 

Global hQuery.l
Global RetVal.l
Global Core.l

Global SI.SYSTEM_INFO

;#PDH_CSTATUS_VALID_DATA = $0
#PDH_CSTATUS_NEW_DATA = $1

;ich mag keine Structuren...
Core = AllocateMemory(64)              ;für max. 4 Cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue 

Prototype.d ProtoValue(Para1.l, Para2.l)    ;CallFunction geht nicht wegen Double-Rückgabewert! 

Procedure.l cpu_count()                ;Anzahl der Cores ermittlen 
  GetSystemInfo_(@SI) 
  ProcedureReturn SI\dwNumberOfProcessors 
EndProcedure 

If OpenLibrary(0, "PDH.DLL")           ;MS-File in \System32 
  RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery)
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhOpenQuery fehlgeschlagen!")  
  EndIf
 
  cpu_count()
 
  For i=0 To SI\dwNumberOfProcessors - 1
    RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Prozessor("+ Str(i) +")\Prozessorzeit (%)", Core+4*i)   ;Counter
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i) +" fehlgeschlagen!")  
    EndIf
  Next 
  
  Repeat 
    CallFunction(0, "PdhCollectQueryData", hQuery)
    Auslastung$=""
    For i=0 To SI\dwNumberOfProcessors - 1
      Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue")
      A.l=i<<3
      B.d=Core+32+A                    ;dblValue 
      B = Value(PeekL(Core+4*i), Core+16+i<<2)
      Auslastung$ + "Auslastung Core" + Str(i)+" = "+ StrD(B, 2) + "%" + Space(20)
      If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o.
        A = -1                         ;war kein gültiger Wert
        Break
      EndIf     
    Next 

    If A <> -1
      Debug Auslastung$
    EndIf
    Delay(500)
  ForEver 

  CallFunction(0, "PdhCloseQuery", hQuery)
  CloseLibrary(0)
EndIf 
Gruss
Helle
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

Danke schön, Helle !
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Post by ts-soft »

You can import the functions from pdh.lib

And it works on vista, thanks
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
SMartin
User
User
Posts: 19
Joined: Thu Aug 16, 2007 6:08 am
Location: Las Vegas

English Version

Post by SMartin »

Here's an English versions of Helle's code.

Code: Select all

;- CPU extent of utilization determination with the PDH.DLL, also for Multi core CPU's
;- Win2k, WinXP, Vista(?) 
;- "Helle" Klaus Helbing, 22.03.2008, PB4.10 
;- Simply intended to show the feasibility

Global hQuery.l 
Global RetVal.l 
Global Core.l 

Global SI.SYSTEM_INFO 

;#PDH_CSTATUS_VALID_DATA = $0 
#PDH_CSTATUS_NEW_DATA = $1 

;I do not like Structures....
Core = AllocateMemory(64)             ;for max. 4 cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue

Prototype.d ProtoValue(Para1.l, Para2.l)    ;CallFunction does not work because of a double return value!

;Number of cores 
Procedure.l cpu_count()            
  GetSystemInfo_(@SI) 
  ProcedureReturn SI\dwNumberOfProcessors 
EndProcedure 

If OpenLibrary(0, "PDH.DLL")           ;MS-File in \System32 
  RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery) 
  If RetVal 
    MessageRequester("Error !", "Unable to call function PdhOpenQuery()!")  
  EndIf 
  
  cpu_count() 
  
  For i=0 To SI\dwNumberOfProcessors - 1 
    RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core+4*i)   ;Counter 
    If RetVal 
      MessageRequester("Error !", "Call to function PdhVbAddCounter() for core "+ Str(i) +" failed!")  
    EndIf 
  Next 
  
  Repeat 
    CallFunction(0, "PdhCollectQueryData", hQuery) 
    ExtentOfUtilization$="" 
    For i=0 To SI\dwNumberOfProcessors - 1 
      Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue") 
      A.l=i<<3 
      B.d=Core+32+A                    ;dblValue 
      B = Value(PeekL(Core+4*i), Core+16+i<<2) 
      ExtentOfUtilization$ + "Extent of core utilization " + Str(i)+" = "+ StrD(B, 2) + "%" + Space(20) 
      If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o. 
        A = -1                         ;invalid value
        Break 
      EndIf      
    Next 

    If A <> -1 
      Debug ExtentOfUtilization$ 
    EndIf 
    Delay(500) 
  ForEver 

  CallFunction(0, "PdhCloseQuery", hQuery) 
  CloseLibrary(0) 
EndIf 
chris319
Enthusiast
Enthusiast
Posts: 782
Joined: Mon Oct 24, 2005 1:05 pm

Re: CPU Usage Multi-core

Post by chris319 »

This version compiles and runs:

Code: Select all

    ;- CPU extent of utilization determination with the PDH.DLL, also for Multi core CPU's
    ;- Win2k, WinXP, Vista(?)
    ;- "Helle" Klaus Helbing, 22.03.2008, PB4.10
    ;- Simply intended to show the feasibility

    Global hQuery.l
    Global RetVal.l
    Global Core.l

    Global SI.SYSTEM_INFO

    ;#PDH_CSTATUS_VALID_DATA = $0
    #PDH_CSTATUS_NEW_DATA = $1

    ;I do not like Structures....
    Core = AllocateMemory(64) ;for max. 4 cores, 0-15=Counter, 16-31=PdhStatus, 32-63=dblValue

    Prototype.d ProtoValue(Para1.l, Para2.l) ;CallFunction does not work because of a double return value!

    ;Number of cores
    Procedure.l cpu_count()           
      GetSystemInfo_(@SI)
      ProcedureReturn SI\dwNumberOfProcessors
    EndProcedure
    
OpenConsole()
    
    If OpenLibrary(0, "PDH.DLL") = 0         ;MS-File in \System32
      MessageRequester("Error", "Unable to open PDH.DLL.")
      CloseConsole()
      End
    EndIf
  
      RetVal = CallFunction(0, "PdhOpenQuery", 0, 1, @hQuery)
      If RetVal
        MessageRequester("Error", "Unable to call function PdhOpenQuery().") 
      EndIf
     
      cpu_count()
     
; Function PdhVbAddCounter( _ ByVal QueryHandle As Long, _ ByVal CounterPath As String, _ ByVal CounterHandle As Long _ ) As Long
; Parameters
; 
; QueryHandle
; ID of the query To which this counter is To be assigned. This value is returned by the PdhVbOpenQuery function.
; 
; CounterPath
; Text string that specifies the name of the counter path To add To the query. The contents of this string must be a valid counter path, As obtained from the counter browser Or other source.
; 
; CounterHandle
; Unique reference that identifies this counter in the query. This variable must be initialized To zero before the function is called. It contains a valid value on Return only If the function completes successfully.
      For i = 0 To SI\dwNumberOfProcessors - 1
;        RetVal = CallFunction(0, "PdhVbAddCounter", hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core+4*i)   ;Counter
        RetVal = CallFunction(hQuery, "\Processor(" + Str(i) + ")\% Processor Time", Core + 4 * i)   ;Counter

        If RetVal
          MessageRequester("Error", "Call to function PdhVbAddCounter() for core "+ Str(i) +" failed.") 
        EndIf
      Next
     
      Repeat
        CallFunction(0, "PdhCollectQueryData", hQuery)
        ExtentOfUtilization$=""
        For i=0 To SI\dwNumberOfProcessors - 1
          Value.ProtoValue = GetFunction(0, "PdhVbGetDoubleCounterValue")
          A.l=i<<3
          B.d=Core+32+A ;dblValue
          B = Value(PeekL(Core+4*i), Core+16+i<<2)
;          ExtentOfUtilization$ + "Extent of core utilization " + Str(i)+" = "+ StrD(B, 2) + "%" + Chr(9) ;Space(20)
          ExtentOfUtilization$ + "Core "  + Str(i) + ": " + StrD(B, 2) + "%" + Chr(9) ;Space(20)
          If PeekL(Core+16+i<<2) > #PDH_CSTATUS_NEW_DATA  ;s.o.
            A = -1 ;invalid value
            Break
          EndIf     
        Next

        If A <> -1
          PrintN(ExtentOfUtilization$)
        EndIf
        Delay(500)
        If Inkey() <> "": Break: EndIf
      ForEver

      CallFunction(0, "PdhCloseQuery", hQuery)
      CloseLibrary(0)
      CloseConsole()
      End
User avatar
GG
Enthusiast
Enthusiast
Posts: 266
Joined: Tue Jul 26, 2005 12:02 pm
Location: Lieusaint (77), France

Re: CPU Usage Multi-core

Post by GG »

Number of cores well detected, but I've always 0.00% per core whatever I do. :shock:

Anyone has the same symptom ?

Pb 4.61 / Windows XP 32 bits
Purebasic 6.12 64 bits - Windows 11 Pro 64 bits 23H2
User avatar
blueb
Addict
Addict
Posts: 1116
Joined: Sat Apr 26, 2003 2:15 pm
Location: Cuernavaca, Mexico

Re: CPU Usage Multi-core

Post by blueb »

GG wrote:Number of cores well detected, but I've always 0.00% per core whatever I do. :shock:

Anyone has the same symptom ?
Yes.. the same results

Purebasic 5.0b3 (x86) - Windows 7 Pro 64 SP1
- It was too lonely at the top.

System : PB 6.21(x64) and Win 11 Pro (x64)
Hardware: AMD Ryzen 9 5900X w/64 gigs Ram, AMD RX 6950 XT Graphics w/16gigs Mem
User avatar
Zebuddi123
Enthusiast
Enthusiast
Posts: 796
Joined: Wed Feb 01, 2012 3:30 pm
Location: Nottinghamshire UK
Contact:

Re: CPU Usage Multi-core

Post by Zebuddi123 »

Hi to All

RE: Test code

Declare cpu_count() ; .l missing from Declare


Thanks for sharing

Zebuddi. :D
malleo, caput, bang. Ego, comprehendunt in tempore
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: CPU Usage Multi-core

Post by Helle »

Aua, my youth :mrgreen: !
Check this (my German version):

Code: Select all

;- CPU-Auslastung-Ermittlung mit der PDH.DLL
;- "Helle" Klaus Helbing, 09.10.2012, tested with PB4.61 (x64), Win7/64 and PB4.61 (x86), Win-XP
;- Use Debug

If OpenLibrary(0, "PDH.DLL")                     ;MS-File in \System32
  SI.SYSTEM_INFO
  #PDH_CSTATUS_NEW_DATA = $1
  #PROCESSOR_ARCHITECTURE_AMD64 = $9

  GetSystemInfo_(@SI)                            ;Anzahl der Cores ermitteln
  AnzCore.l = SI\dwNumberOfProcessors
  Is64.i = SI\wProcessorArchitecture             ;w -> i
  Buffer.i = AllocateMemory(8 * AnzCore)
  CoreLast.d
  CoreLast64.d
  hQuery.l

  Prototype.l ProtoOpenQuery(Para1.l)
  Prototype.l ProtoCloseQuery(Para1.l)
  Prototype.l ProtoCollectData(Para1.l)
  Prototype.d ProtoAuslastung(Para1.l, Para2.l)
  Prototype.l ProtoAddCounter(Para1.l, Para2.i, Para3.i)

  Lang = GetSystemDefaultLangID_() & $FFFF
  Select Lang
    Case $407                                    ;GE
      P1$ = "Prozessor"
      P2$ = "Prozessorzeit" 
    Case $409                                    ;EN_US   ckeck it :-)!
      P1$ = "Processor"
      P2$ = "Processor Time"
    Case $40C                                    ;FR      check it :-)!
      P1$ = "Processeur"
      P2$ = "temps Processeur"
    ;.....  Other Languages

  EndSelect

  OpenQuery.ProtoOpenQuery = GetFunction(0, "PdhVbOpenQuery")
  CloseQuery.ProtoCloseQuery = GetFunction(0, "PdhCloseQuery")       ;PdhVbCloseQuery z.B. nicht für Server 2003 !
  CollectData.ProtoCollectData = GetFunction(0, "PdhCollectQueryData")
  AddCounter.ProtoAddCounter = GetFunction(0, "PdhVbAddCounter")
  Auslastung.ProtoAuslastung = GetFunction(0, "PdhVbGetDoubleCounterValue")
 
  RetVal = OpenQuery(@hQuery)
   
  If RetVal
    MessageRequester("Fehler !", "Aufruf von PdhVbOpenQuery fehlgeschlagen!")  ;Error-Message OpenQuery
    End
  EndIf

  For i = 0 To AnzCore - 1
    Proz$ = "\" + P1$ + "(" + Str(i) + ")\" + P2$ + " (%)"
    RetVal = AddCounter(hQuery, @Proz$, Buffer + (i << 2))
    If RetVal
      MessageRequester("Fehler !", "Aufruf von PdhVbAddCounter für Core"+ Str(i) + " fehlgeschlagen!")  ;Error-Message AddCounter
      ;End
    EndIf
  Next
 
  Repeat
    CollectData(hQuery)
    Auslastung$ = ""
    For i = 0 To AnzCore - 1
      CoreLast = Auslastung(PeekL(Buffer + (4 * i)), PeekL(Buffer + (4 * AnzCore) + (i << 2)))
      !movsd [v_CoreLast64],xmm0                 ;64-Bit-DLL: Float-/Double-Return-Value in XMM0!
      If Is64 = #PROCESSOR_ARCHITECTURE_AMD64
        CoreLast = CoreLast64
      EndIf
      Auslastung$ + "Core" + Str(i) + " = " + StrD(CoreLast, 2) + "%" + Space(20)
      If PeekL(Buffer + (4 * AnzCore) + (i << 2)) > #PDH_CSTATUS_NEW_DATA ;s.o.
        A = -1                                   ;war kein gültiger Wert
        Break
      EndIf     
    Next
    If A <> -1
      Debug Auslastung$
    EndIf
    Delay(1000)
  ForEver
 
  CloseQuery(hQuery)
  CloseLibrary(0)
EndIf
Have fun!
Helle
Last edited by Helle on Tue Oct 09, 2012 11:15 am, edited 2 times in total.
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: CPU Usage Multi-core

Post by doctorized »

Helle wrote:Aua, my youth :mrgreen: !
Check this (my German version):
Your code is not working for me on Win 7 greek x64 for PB 4.61 x86 and x64.
Error message "Aufruf von PdhVbAddCounter fur Core"+ Str(i) + " fehlgeschlagen!" for every core of my cpu.
After this 0.00% is shown for every core on every loop.
I need the greek phrases for P1$ and P2$? I think you can take them somehow programmatically. If I find it I'll post it.
User avatar
ts-soft
Always Here
Always Here
Posts: 5756
Joined: Thu Jun 24, 2004 2:44 pm
Location: Berlin - Germany

Re: CPU Usage Multi-core

Post by ts-soft »

Works only as 64-Bit program.
PureBasic 5.73 | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Old bugs good, new bugs bad! Updates are evil: might fix old bugs and introduce no new ones.
Image
Helle
Enthusiast
Enthusiast
Posts: 178
Joined: Wed Apr 12, 2006 7:59 pm
Location: Germany
Contact:

Re: CPU Usage Multi-core

Post by Helle »

Sorry, see new.
My problem: No 32-Bit-OS for tests (in VM only 1 Core; but... my mistake).
Yes, P1$ and P2$ are language-sensitive!
Gruss
Helle
User avatar
doctorized
Addict
Addict
Posts: 882
Joined: Fri Mar 27, 2009 9:41 am
Location: Athens, Greece

Re: CPU Usage Multi-core

Post by doctorized »

Helle wrote:Sorry, see new.
My problem: No 32-Bit-OS for tests (in VM only 1 Core; but... my mistake).
Yes, P1$ and P2$ are language-sensitive!
Gruss
Helle
Use this:

Code: Select all

#COUNTERPERF_PROCESSOR = 238
#COUNTERPERF_PERCENTPROCESSORTIME = 6

Procedure.s GetCPUCounter(strInstance.s)
    ; get Object & Counter names for CPU Usage
    ; Different languages of windows use different names so we use a look-up!
	If OpenLibrary(0, "pdh.dll")  
		*F = GetFunction(0, "PdhLookupPerfNameByIndexA")
		If *F
			 NameLen.l: ObjectName.s: CounterName.s
		    
		    NameLen = #MAX_PATH
		    ObjectName = Space(NameLen)
		    i = CallFunctionFast(*F,#Null, #COUNTERPERF_PROCESSOR, @ObjectName, @NameLen)
       
		    NameLen = #MAX_PATH
		    CounterName = Space(NameLen)
		    
		    i = CallFunctionFast(*F,#Null, #COUNTERPERF_PERCENTPROCESSORTIME, @CounterName, @NameLen)
		    Debug "\" + ObjectName + "(" + strInstance + ")\" + CounterName
		    ProcedureReturn "\" + ObjectName + "(" + strInstance + ")\" + CounterName
		EndIf
		CloseLibrary(0)
	EndIf
EndProcedure
This is what I use in a code of mine.
Post Reply