Multi Core CPU Auslast

    • Offizieller Beitrag

    Hallo

    Hat jemand eine Idee, wie ich von einem Dual oder Quad Core die einzelnen CPU Auslastungen von jedem einzelnen Kern bekomme (also so, wie es auch im Taskmrg angezeigt wird)?
    Im engl Forum gibt es zwar was (CPU Meter), aber erstens is das sehr langsam da über WMI und zweitens wird da nur der erste Core, bzw die gesamte CPU Last angezeigt.

    Hab auch schon msdn durchforstet, aber nichts brauchbares gefunden... Es müsste eigentlich irgendwie über den Systemmonitor (perfmon) gehen, hab aber nichts herrausgefunden :(

    Vielleicht weiß ja einer von euch weiter, währe echt super :thumbup:

    Mfg Spider

  • eigene mmc speichern mit den passenden Leistungsindikatoren und das Log auswerten,
    willst Du nur die Werte oder nur die Optik oder beides?
    Die MMC könne man ja hiner einer eigenen Gui verstecken :P
    nur da sutomatische protokollieren muss man evtl. mitgeben vielleicht wird der Schalter auch in der mmc gespeichertTabellengenerator.rar

    Wenn Du die MMC nur zur Anzeige nutzen willst unter Optionen kann man konfigurieren was man in der MMC darf ;)

    Achtung Anfänger! :whistling:

    Betrachten des Quellcodes auf eigene Gefahr, bei Übelkeit,Erbrechen,Kopfschmerzen übernehme ich keine Haftung. 8o

    2 Mal editiert, zuletzt von Dietmar (19. Dezember 2008 um 00:06)

    • Offizieller Beitrag

    Hallo

    Danke schonmal für deine Antwort :thumbup:
    Ich brauche nur die Werte, will also keine Anzeige (also nicht per ActiveX in eine GUI einfügen ;) )
    Das Problem ist, dass das Script ja nicht nur für mich ist, sondern ich das Publik machen will, also funktioniert die möglichkeit mit Hide nicht.
    Würde gerne schon was sicheres haben und nicht mit ControlGetText da rum hantieren ;)
    Am besten währe wie gesagt ein direkter Dll Aufruf mit ggf. Struct oder zunot halt auch ein WMI aufruf. Da hab ich aber wie gesagt noch nichts gescheites gefunden.

    Mfg Spider

    • Offizieller Beitrag

    Ich habe da was gefunden, kannst ja mal schauen ob es paßt.

    http://www.hobbl.com/gmdlls/cpuusage

    • Offizieller Beitrag

    Hallo

    Leider keine Erklärung dabei.
    Und das funktioniert auch nicht ;)

    [autoit]

    $aDLL = DllCall('CPUusage.dll','int','hobbl_com_init');
    $aDLL = DllCall('CPUusage.dll','int','hobbl_com_getusage');

    [/autoit]

    Aber ich sehe, dass die dll nur auf die Kernel32.dll zugreift. Das habe ich ja auch schön überlegt.
    Hier sind die Funktionen, die die Dll von der Kernel32 benutzt:
    http://img-up.net/?up=UnbenanntDZDvqw.JPG

    Aber vielen Dank schonmal für die Antwort, ich werde es mir nochmal genauer angucken ;)
    Ist natürlich immer schöner, Windows intern zu bleiben ;)

    Mfg Spider

  • Funktioniert das bei dir? Kann's nicht wirklich testen, da ich nur einen Kern habe.

    [autoit]

    $Dll = DllOpen('CPUusage.dll')
    $Cores = DllCall($Dll, 'float', 'hobbl_com_init')
    MsgBox(0,"Prozessoren",$Cores[0])
    DllClose($Dll)

    [/autoit]
    Spoiler anzeigen

    CPU-Auslastung hab ich noch nicht geschafft.

  • Hi,

    Es kann gut sein, dass ich jetzt völlig falsch liege ^^.

    Spoiler anzeigen
    [autoit]

    While 1
    ToolTip(CurrentCPU())
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func CurrentCPU($init = 0)
    Global $liOldIdleTime = 0
    Global $liOldSystemTime = 0
    Local $SYS_BASIC_INFO = 0
    Local $SYS_PERFORMANCE_INFO = 2
    Local $SYS_TIME_INFO = 3

    $SYSTEM_BASIC_INFORMATION = DllStructCreate("int;uint;uint;uint;uint;uint;uint;ptr;ptr;uint;byte;byte;short")
    $status = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", "int", $SYS_BASIC_INFO, _
    "ptr", DllStructGetPtr($SYSTEM_BASIC_INFORMATION), _
    "int", DllStructGetSize($SYSTEM_BASIC_INFORMATION), _
    "int", 0)

    If $status[0]Then Return -1

    While 1
    $SYSTEM_PERFORMANCE_INFORMATION = DllStructCreate("int64;int[76]")
    $SYSTEM_TIME_INFORMATION = DllStructCreate("int64;int64;int64;uint;int")

    $status = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", "int", $SYS_TIME_INFO, _
    "ptr", DllStructGetPtr($SYSTEM_TIME_INFORMATION), _
    "int", DllStructGetSize($SYSTEM_TIME_INFORMATION), _
    "int", 0)

    If $status[0]Then Return -2

    $status = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", "int", $SYS_PERFORMANCE_INFO, _
    "ptr", DllStructGetPtr($SYSTEM_PERFORMANCE_INFORMATION), _
    "int", DllStructGetSize($SYSTEM_PERFORMANCE_INFORMATION), _
    "int", 0)

    If $status[0] Then Return -3

    If $init = 1 Or $liOldIdleTime = 0 Then
    $liOldIdleTime = DllStructGetData($SYSTEM_PERFORMANCE_INFORMATION, 1)
    $liOldSystemTime = DllStructGetData($SYSTEM_TIME_INFORMATION, 2)
    Sleep(1000)
    If $init = 1 Then Return -99
    Else
    $dbIdleTime = DllStructGetData($SYSTEM_PERFORMANCE_INFORMATION, 1) - $liOldIdleTime
    $dbSystemTime = DllStructGetData($SYSTEM_TIME_INFORMATION, 2) - $liOldSystemTime
    $liOldIdleTime = DllStructGetData($SYSTEM_PERFORMANCE_INFORMATION, 1)
    $liOldSystemTime = DllStructGetData($SYSTEM_TIME_INFORMATION, 2)

    $dbIdleTime = $dbIdleTime / $dbSystemTime

    $dbIdleTime = 100.0 - $dbIdleTime * 100.0 / DllStructGetData($SYSTEM_BASIC_INFORMATION, 11) + 0.5
    Return $dbIdleTime
    EndIf
    $SYSTEM_PERFORMANCE_INFORMATION = 0
    $SYSTEM_TIME_INFORMATION = 0
    WEnd
    EndFunc ;==>CurrentCPU

    [/autoit]

    Current CPU

    Dadurch bin ich drauf gekommen NtQuerySystemInformation

    • Offizieller Beitrag

    Hallo

    Danke euch allen erstmal für die Antworten :)
    funkey: Jup, er zeigt mir 4 Kerne an, aber soweit war ich ja auch schon. Die Frage ist halt, wie man damit die CPU Auslast anzeigt. Aber schon nicht schlecht :)
    @die anderen beiden: Danke, aber ich will ja eben nicht die CPU Last vom System sondern von jedem einzelnen Kern haben ;) Also nicht die gesamte CPU Last sondern halt nur von einem Kern... Trotzdem Danke für die Mühe :thumbup:

    Mfg Spider

  • Moin Spider,

    ich habe da ein Bsp. in C++ gefunden. Wenn Du Probleme beim Übersetzen hast kann ich dir helfen ...

    Spoiler anzeigen


    LG
    Greenhorn


    • Offizieller Beitrag

    Hallo

    Wow, vielen Dank, hat mir wirklich weitergeholfen. :)
    Ist leider etwas Langsam, aber es funktioniert einwandfrei ;)
    Für die, den es interessiert:

    Spoiler anzeigen
    [autoit]

    $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2")
    Global $aCPU[5]
    While 1
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor", "WQL", 48)
    If IsObj($colItems) Then
    $i = 0
    For $objItem In $colItems
    $aCPU[$i] = $objItem.PercentProcessorTime
    $i += 1
    Next
    EndIf
    ConsoleWrite("============" & @CRLF)
    ConsoleWrite("Core 1: "&$aCPU[0] & @CRLF)
    ConsoleWrite("Core 2: "&$aCPU[1] & @CRLF)
    ConsoleWrite("Core 3: "&$aCPU[2] & @CRLF)
    ConsoleWrite("Core 4: "&$aCPU[3] & @CRLF)
    ConsoleWrite("Gesamt: "&$aCPU[4] & @CRLF)
    WEnd

    [/autoit]

    Mfg Spider

  • Mit einem Refresher geht es schneller ;) (musste sogar Sleep 500 einbauen, damit nicht zu oft gelesen wird.

    Spoiler anzeigen
    [autoit]

    $objRefresher = ObjCreate("WbemScripting.SWbemRefresher")

    [/autoit] [autoit][/autoit] [autoit]

    $objWMIService = ObjGet("winmgmts:\\localhost\root\CIMV2")

    [/autoit] [autoit][/autoit] [autoit]

    $objRefreshableItem = $objRefresher.AddEnum($objWMIService , "Win32_PerfFormattedData_PerfOS_Processor")

    [/autoit] [autoit][/autoit] [autoit]

    $objRefresher.Refresh

    [/autoit] [autoit][/autoit] [autoit]

    If IsObj($objRefreshableItem) Then
    $i = 0
    For $objItem In $objRefreshableItem.ObjectSet
    $i += 1
    Next
    EndIf
    Global $aCPU[$i]

    [/autoit] [autoit][/autoit] [autoit]

    While 1

    [/autoit] [autoit][/autoit] [autoit]

    $objRefresher.Refresh
    If IsObj($objRefreshableItem) Then
    $i = 0
    For $objItem In $objRefreshableItem.ObjectSet
    $aCPU[$i] = $objItem.PercentProcessorTime
    $i += 1
    Next
    EndIf
    ConsoleWrite("============" & @CRLF)
    For $i = 0 To UBound($aCPU)-2
    ConsoleWrite("Core "&$i+1&": "&$aCPU[$i] & @CRLF)
    Next
    ConsoleWrite("Gesamt: "&$aCPU[UBound($aCPU)-1] & @CRLF)
    Sleep(500)
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func OnAutoItExit()
    $objRefresher.DeleteAll
    EndFunc

    [/autoit]
  • Hab mal eine Funktion geschrieben die ohne wmi auskommt.
    Würde mich freuen wenn das mal jemand testen könnte und guckt ob die werte zumindest etwa hinkommen. Thx

    Spoiler anzeigen
    [autoit]

    ;#####################################################################
    ;#
    ;# Funtion _GetCPUUsage()
    ;# Ermittelt die Auslastung der CPU, Multicore Kompatibel
    ;#
    ;# Rückgabewert: Array
    ;# Array[0] Anzahl der CPUs, Fehler wenn negativ
    ;# Array[n] Auslastung der n-ten CPU in Prozent
    ;#
    ;# Fehler: -1 Fehler beim 1. Dll Aufruf
    ;# -2 Fehler beim 2. Dll Aufruf
    ;# -3 Fehler beim 3. Dll Aufruf
    ;#
    ;# Autor: Bitboy
    ;#####################################################################
    Func _GetCPUUsage()
    Local Const $SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = 8
    Local Const $SYSTEM_TIME_INFO = 3
    Local Const $tagS_SPPI = "int64 IdleTime;int64 KernelTime;int64 UserTime;int64 DpcTime;int64 InterruptTime;long InterruptCount"

    [/autoit] [autoit][/autoit] [autoit]

    Local $CpuNum, $IdleOldArr[1],$IdleNewArr[1], $tmpStruct
    Local $timediff = 0, $starttime = 0
    Local $S_SYSTEM_TIME_INFORMATION, $S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
    Local $RetArr[1]

    [/autoit] [autoit][/autoit] [autoit]

    Local $S_SYSTEM_INFO = DllStructCreate("ushort dwOemId;short wProcessorArchitecture;dword dwPageSize;ptr lpMinimumApplicationAddress;" & _
    "ptr lpMaximumApplicationAddress;long_ptr dwActiveProcessorMask;dword dwNumberOfProcessors;dword dwProcessorType;dword dwAllocationGranularity;" & _
    "short wProcessorLevel;short wProcessorRevision")

    [/autoit] [autoit][/autoit] [autoit]

    ;Anzahl der CPUs bestimmen
    $err = DllCall("Kernel32.dll", "none", "GetSystemInfo", "ptr",DllStructGetPtr($S_SYSTEM_INFO))

    [/autoit] [autoit][/autoit] [autoit]

    If @error Or Not IsArray($err) Then ;Fehler beim 1. Dll Aufruf
    Return $RetArr[0] = -1
    Else
    $CpuNum = DllStructGetData($S_SYSTEM_INFO, "dwNumberOfProcessors")
    ReDim $RetArr[$CpuNum+1]
    $RetArr[0] = $CpuNum
    EndIf
    $S_SYSTEM_INFO = 0

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    ;Erstellen der Struktur für die Prozessor Performance
    $S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = DllStructCreate($tagS_SPPI)
    ;Größe Struktur um später vielfache (MultiCore) der Structur lesen zu können
    $StructSize = DllStructGetSize($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)
    ;Erstellen einer Pufferstruktur
    $S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = DllStructCreate("byte puffer[" & $StructSize * $CpuNum & "]")
    ;Pointer zum wiederfinden
    $pointer = DllStructGetPtr($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)

    [/autoit] [autoit][/autoit] [autoit]

    $err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", _
    "int", $SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, _
    "ptr", DllStructGetPtr($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), _
    "int", DllStructGetSize($S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), _
    "int", 0)

    [/autoit] [autoit][/autoit] [autoit]

    ;Fehler beim 2. Dll Aufruf
    If $err[0] Then
    Return $RetArr[0] = -2
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    ;Struktur und Dll-Aufruf für Zeitmessung
    Local $S_SYSTEM_TIME_INFORMATION = DllStructCreate("int64;int64;int64;uint;int")
    $err = DllCall("ntdll.dll", "int", "NtQuerySystemInformation", _
    "int", $SYSTEM_TIME_INFO, _
    "ptr", DllStructGetPtr($S_SYSTEM_TIME_INFORMATION), _
    "int", DllStructGetSize($S_SYSTEM_TIME_INFORMATION), _
    "int", 0)

    ;Fehler beim 3. Dll Aufruf
    If $err[0] Then
    Return $RetArr[0] = -3
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    If $starttime = 0 Then ;Startwerte Ermitteln
    ReDim $IdleOldArr[$CpuNum]
    ;Start-Informationen Auslesen
    For $i = 0 to $CpuNum -1
    $tmpStruct = DllStructCreate($tagS_SPPI, $Pointer + $i*$StructSize)
    $IdleOldArr[$i] = DllStructGetData($tmpStruct,"IdleTime")
    Next
    ;Startzeit ermitteln
    $starttime = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2)
    ;Verzögerung um einen Zeitunterschied sicher zu stellen
    Sleep(500)
    Else
    ReDim $IdleNewArr[$CpuNum]
    ;Neue Informationen auslesen
    For $i = 0 to $CpuNum -1
    $tmpStruct = DllStructCreate($tagS_SPPI, $Pointer + $i*$StructSize)
    $IdleNewArr[$i] = DllStructGetData($tmpStruct,"IdleTime")
    Next

    ;Zeitdifferenze in 100 nanosekunden
    $timediff = DllStructGetData($S_SYSTEM_TIME_INFORMATION, 2) - $starttime

    ;Auslastung errechnen
    For $i=0 to $CpuNum -1
    $RetArr[$i+1] = Round(100-(($IdleNewArr[$i] - $IdleOldArr[$i]) * 100 / $timediff))
    Next

    Return $RetArr
    EndIf

    ;Speicher wieder frei geben
    $S_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION = 0
    $S_SYSTEM_TIME_INFORMATION = 0
    $tmpStruct = 0
    WEnd
    EndFunc

    [/autoit]
  • Hi,
    in der c´t 7/2009 ist ab Seite 102 ein Artikel zu diesem Thema, u.a. ist auch das Vorgehen zum Verteilen von Threads auf die verschiedenen Kerne beschrieben.

    ciao
    Andy

  • in der Funktion selbst steht ein Sleep(500)

    Ich war und bin mir immer noch nicht wirklich sicher wie ich das mit den Pausenzeiten in der Funktion regeln soll. immerhin muss eine Zeitdifferenz da sein. Aber du kannst gerne mal ein Sleep(1) draus machen oder ganz entfernen und sagen ob es besser ist. Immerhin müsste es ja schneller gehen wenn man direkt auf die Api zugreift.

    Edit: Habs grade mal ausprobiert, sleep ganz weglassen geht nicht, dann ist die Zeitdifferenz 0 und es endet mit einem völlig unsinnigen wert für die Prozessorauslastung.
    Seltsam, AutoIT kennt wohl keinen "Devided by Zero" Fehler

    Naja Sleep(10) geht aber, und ich denke das sollte ausreichend schnell sein.

    3 Mal editiert, zuletzt von Bitboy (7. April 2009 um 19:26)