CPUUsage Multi-processeur

Programmation d'applications complexes
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

CPUUsage Multi-processeur

Message par Gillou »

Bonjour à tous,

Ce code est un début de projet pour l'évolution de l'un de mes progs, il a pour but de vous donner le pourcentage CPU utilisé par le système pour chaque processeur ou coeur.

Pourriez-vous me dire si ce code fonctionne sur votre ordi, en m'indiquant votre version de Windows

MERCI D'AVANCE !!!
   Structure SYSTEM_BASIC_INFORMATION
    reserved.l
    TimerResolution.l
    PageSize.l
    NumberOfPhysicalPages.l
    LowestPhysicalPageNumber.l
    HighestPhysicalPageNumber.l
    AllocationGranularity.l
    MinimumUserModeAddress.l
    MaximumUserModeAddress.l
    ActiveProcessorsAffinityMask.l
    NumberOfProcessors.l
EndStructure

Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    Reserved1.q[3]
EndStructure

#SystemBasicInformation = 0
#SystemProcessorPerformanceInformation = 8
#SysProcPerfInfoLength = 48

#PROCESS_QUERY_INFORMATION = $400
#HUNDRED_NANOSEC = 10000000

DeclareDLL.l GetNumberOfProcessor()

Global Frequency.q, TimeStart.q

Global NumberOfProcessors = GetNumberOfProcessor()

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 KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.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)

ProcedureDLL.l GetNumberOfProcessor() ; Retourne le nombre de processeur
    Protected resultat, Lib, SBI.SYSTEM_BASIC_INFORMATION
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemBasicInformation , @SBI, SizeOf (SYSTEM_BASIC_INFORMATION), 0) = 0
            resultat = SBI\NumberOfProcessors
         EndIf
         CloseLibrary (Lib)
     EndIf
     ProcedureReturn resultat
EndProcedure

Procedure.d Div10k(Value.q)
     ProcedureReturn Value/10000
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * NumberOfProcessors, 0) = 0
             If start = #True
                KernelTimesStart(NumberOfProcessors) = 0
                IdleTimesStart(NumberOfProcessors) = 0
                UserTimesStart(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStart(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             Else
                KernelTimesStop(NumberOfProcessors) = 0
                IdleTimesStop(NumberOfProcessors) = 0
                UserTimesStop(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStop(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStop(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) +Div10k( CpuInfo(i)\IdleTime)
                    UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             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) * 10000 : 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 : CpuUsages(i) = 100 : EndIf
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, StrD (KernelTimesStart(i), 3), 2)
         SetGadgetItemText (1, i, StrD (UserTimesStart(i), 3), 3)
         SetGadgetItemText (1, i, StrD (IdleTimesStart(i), 3), 4)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
    CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) / NumberOfProcessors
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, StrD (KernelTimesStart(NumberOfProcessors), 3), 2)
     SetGadgetItemText (1, NumberOfProcessors, StrD (UserTimesStart(NumberOfProcessors), 3), 3)
     SetGadgetItemText (1, NumberOfProcessors, StrD (IdleTimesStart(NumberOfProcessors), 3), 4)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 535, 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, 515, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "Kernel Time" , 120)
     AddGadgetColumn (1, 3, "User Time" , 120)
     AddGadgetColumn (1, 4, "Idle Time" , 120)
    
     For i=0 To NumberOfProcessors-1
         AddGadgetItem (1, -1, "CPU " + Str (i))
     Next
     AddGadgetItem (1, 2, "CPU TOTAL" )
    
     SetTimer_ ( WindowID (Win), 1, 1000, @refresh())
     Repeat
         Select WaitWindowEvent ()
             Case #PB_Event_Gadget
                 Select EventGadget ()
                     ;Case
                 EndSelect
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf
Avatar de l’utilisateur
venom
Messages : 3128
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Message par venom »

salut Gillou ,

j'ai un dual core chez moi et sa fonctionne niquel :wink: .
mais il me semble que dobro avait deja fait un truck comme sa non ?
ou je me trompe de personne :oops: .


@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

Arf, comme quoi j'aurais mieux fait de chercher avant (au moins je perds pas la main...)

en tout cas merci du test

;)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

venom a écrit :salut Gillou ,

j'ai un dual core chez moi et sa fonctionne niquel :wink: .
mais il me semble que dobro avait deja fait un truck comme sa non ?
ou je me trompe de personne :oops: .


@++
non j'ai repris un truc de Cpl Bator, qui te donne le nombre de Core dispo

et possiblement donne la possibilité d'utiliser l'un ou l'autre Core (mais je peux pas debugger n'ayant pas de multi core !!)

le prg de Gillou est complementaire , puisqu'il apporte plus d'informations :)
Avatar de l’utilisateur
venom
Messages : 3128
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Message par venom »

a oui exacte autant pour moi :wink: .


@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
Droopy
Messages : 1151
Inscription : lun. 19/juil./2004 22:31

Message par Droopy »

Semble fonctionner sur mon core 2 duo 4300
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

Voila ce qui se passe quand on ne prend plus le temps de venir sur le fofo, on rate plein de truc super,...
je viens de regarder ton code Dobro et effectivement ça va me servir, un boulot de moins... :D

Et Merci de vos tests à tous!
Avatar de l’utilisateur
Ar-S
Messages : 9539
Inscription : dim. 09/oct./2005 16:51
Contact :

Message par Ar-S »

Marche impec sur mon A64 X2 4200+
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Gillou a écrit :Voila ce qui se passe quand on ne prend plus le temps de venir sur le fofo, on rate plein de truc super,...
je viens de regarder ton code Dobro et effectivement ça va me servir, un boulot de moins... :D

Et Merci de vos tests à tous!
attention pas pu tester, faute de Multicore chez moi :)
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

@Dobro, Ok pas de problèmes, je viens de tester et en effet quelques corrections à revoir mais déjà, il y a une base d'où partir déjà excellent

@Ar-s, Merci pour le test

Pour ceux qui on testé, d'après ce que j'ai compris vous avez tous des doubles coeurs (sous XP supposé?)

Personne avec un simple coeur ou un quadri ou plus?
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

Voici mon test avec un QuadCore, et Vista:

Image

Donc je dirais appriori que c'est pas très clair ;)
La fenetre du dessous est un mesh 3D qui tourne, pour pousser un des
coeur un petit peu (meme si une bonne part du boulot est fait par la carte video)
Force et sagesse...
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

Effectivement, c'est pas terrible, gros bug dans l'affaire. Merci du test et de l'image :D

Et je me retrouve dans la situation de Dobro à essayer de trouver une panne et en corrigeant à l'aveuglette ;), au moins ça va me faire chercher

__________________


Correction du code, c'est loin de code final mais ça va m'aider à mieux cerner d'où vient l'erreur



Structure SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    IdleTime.q
    KernelTime.q
    UserTime.q
    Reserved1.q[3]
EndStructure

#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 KernelTimesStop.d(NumberOfProcessors+1)
Global Dim UserTimesStop.d(NumberOfProcessors+1)
Global Dim IdleTimesStop.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() ; Retourne le nombre de processeur
    Protected SI.SYSTEM_INFO
     GetSystemInfo_ (@SI)
     ProcedureReturn SI\dwNumberOfProcessors
EndProcedure

Procedure.d Div10k(Value.q)
     If Value > #HUNDRED_NANOSEC
         ProcedureReturn Value/10000
     Else
         ProcedureReturn Value
     EndIf
EndProcedure

Procedure GetProcessorsTimes(start = #True )
    Protected Lib
    Lib = OpenLibrary ( #PB_Any , "ntdll.dll" )
     If Lib
         If CallFunction (Lib, "NtQuerySystemInformation" , #SystemProcessorPerformanceInformation , @CpuInfo(), #SysProcPerfInfoLength * NumberOfProcessors, 0) = 0
             If start = #True
                KernelTimesStart(NumberOfProcessors) = 0
                IdleTimesStart(NumberOfProcessors) = 0
                UserTimesStart(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStart(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStart(NumberOfProcessors) = KernelTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStart(NumberOfProcessors) = IdleTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStart(NumberOfProcessors) = UserTimesStart(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             Else
                KernelTimesStop(NumberOfProcessors) = 0
                IdleTimesStop(NumberOfProcessors) = 0
                UserTimesStop(NumberOfProcessors) = 0
                 For i = 0 To NumberOfProcessors - 1
                    KernelTimesStop(i) = Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(i) = Div10k(CpuInfo(i)\IdleTime)
                    UserTimesStop(i) = Div10k(CpuInfo(i)\UserTime)
                    KernelTimesStop(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\KernelTime)
                    IdleTimesStop(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors) +Div10k( CpuInfo(i)\IdleTime)
                    UserTimesStop(NumberOfProcessors) = UserTimesStop(NumberOfProcessors) + Div10k(CpuInfo(i)\UserTime)
                 Next
             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) * 10000 : 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 : CpuUsages(i) = 100 : EndIf
        CpuUsages(i) = CpuUsages(i) * NumberOfProcessors
        CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) + CpuUsages(i)
        KernelTimesStart(i) = KernelTimesStop(i)
        UserTimesStart(i) = UserTimesStop(i)
        IdleTimesStart(i) = IdleTimesStop(i)
         SetGadgetItemText (1, i, StrD (CpuUsages(i), 3), 1)
         SetGadgetItemText (1, i, StrD (KernelTimesStart(i), 3), 2)
         SetGadgetItemText (1, i, StrD (UserTimesStart(i), 3), 3)
         SetGadgetItemText (1, i, StrD (IdleTimesStart(i), 3), 4)
     Next
    
    KernelTimesStart(NumberOfProcessors) = KernelTimesStop(NumberOfProcessors)
    UserTimesStart(NumberOfProcessors) = UserTimesStop(NumberOfProcessors)
    IdleTimesStart(NumberOfProcessors) = IdleTimesStop(NumberOfProcessors)
    
    CpuUsages(NumberOfProcessors) = CpuUsages(NumberOfProcessors) / NumberOfProcessors
    
     SetGadgetItemText (1, NumberOfProcessors, StrD (CpuUsages(NumberOfProcessors), 3), 1)
     SetGadgetItemText (1, NumberOfProcessors, StrD (KernelTimesStart(NumberOfProcessors), 3), 2)
     SetGadgetItemText (1, NumberOfProcessors, StrD (UserTimesStart(NumberOfProcessors), 3), 3)
     SetGadgetItemText (1, NumberOfProcessors, StrD (IdleTimesStart(NumberOfProcessors), 3), 4)
    
    TimeStart = CurTime
EndProcedure

QueryPerformanceFrequency_ (@Frequency)
QueryPerformanceCounter_ (@TimeStart)

GetProcessorsTimes()

Win = OpenWindow ( #PB_Any , 0, 0, 535, 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, 515, 120, "CPU" , 75)
     AddGadgetColumn (1, 1, "% Usage" , 60)
     AddGadgetColumn (1, 2, "Kernel Time" , 120)
     AddGadgetColumn (1, 3, "User Time" , 120)
     AddGadgetColumn (1, 4, "Idle Time" , 120)
    
     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_Gadget
                 Select EventGadget ()
                     ;Case
                 EndSelect
             Case #PB_Event_CloseWindow
                Quit = 1
         EndSelect
     Until Quit = 1
     KillTimer_ ( WindowID (Win), 1)
EndIf
Avatar de l’utilisateur
Jacobus
Messages : 1559
Inscription : mar. 06/avr./2004 10:35
Contact :

Message par Jacobus »

Ca à l'air de fonctionner avec mon double coeur Pentium D820 et c'est très utile cet outil. Je trouve dommage par contre que les temps donnés ne soient pas lisibles au format hh:mm:ss voire ss:ms:ns
J'avais essayé mais sans succès pour ma fonction GetProcessusTime(pid.l) qui récupère le temps processeur d'une application par son id.
ici : http://www.purebasic.fr/french/viewtopic.php?t=7480

Si tu permet je vais tenter une approche graphique de ton code qui mérite qu'on s'y attarde :)
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Gillou
Messages : 373
Inscription : sam. 28/août/2004 17:35
Localisation : Bretagne, 22
Contact :

Message par Gillou »

Pas de problème, tu peux en faire ce que tu veux, mon but final est de faire évoluer un CPU monitor que j'avais conçu il y a quelques années ne gérant à l'époque que du simple coeur.

Et effectivement je vais voir pour convertir au format minutes, secondes...

En tout cas ton code en lien est aussi très intéressant, je vais l'étudier
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

J'ai refais le test. J'ai à priori les mêmes résultats, si ce n'est le total qui est bien
en bas cette fois. :?
Force et sagesse...
Répondre