CPU Auslastung beim QuadCore



  • Hi,

    ich habe ja schon diesen Artikel gefunden: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1177579.html

    So nutze ich das auch..

    so, jetzt aber zu meinem Problem:

    Ich habe einen QuadCore und möchte die CPU-Last pro Core ermitteln. Aber irgendwie funzt das nicht richtig. Der Wert für Core1 und Core2 stimmt, aber der Wert für Core3 + Core4 ist immer das gleiche für Core2.. Ich hab schon das halbe Netz durchsucht...

    Weiß jemand Rat?

    Machine



  • Welche der beiden Varianten hast Du verwendet? WMI? Damit sollte es gehen...



  • oh ich sehe grad, dass ich wohl doch eine andere variante hab... is schon ne weile her 😉 hier mal die files:

    .h:

    #pragma once
    
    #ifndef 	__CPULOAD_H__
    #define 	__CPULOAD_H__
    
    class CCpuLoad
    {
    public:
    	CCpuLoad();
    	virtual ~CCpuLoad();
    
    protected:
    	int CpuInit();					// Initialisierung
    	int CpuExit();					// Deinitialisierung
    
    public:
    	int GetCpuCount();					// CPU-Anzahl abfragen
    	int UpdateCpu();				// CPU-Auslastungsdaten holen
    	int GetCpuLoad(unsigned uCpu);		// CPU-Auslastungs für eine CPU abfragen
    
    };
    #endif
    

    .cpp:

    #include	<windows.h>
    #include	"CpuLoad.h"
    
    #define	PROCESSOR_IDX	238
    #define CPU_USAGE_IDX	6
    
    static	HKEY		 hWin9xKey    = 0;
    static	BOOL		 bIsWinNt	  = 0;
    static	DWORD		 dwDataSize   = 0;
    static	DWORD		 dwWin9xUsage = 0;
    static	__int64		*pCounterAct  = 0;
    static	__int64		*pCounterPre  = 0;
    static	__int64		 iSysTimeAct  = 1;
    static	__int64		 iSysTimePre  = 0;
    static	unsigned	 uCpuCount    = 0;
    static	union
    {
    	PERF_DATA_BLOCK			*o;
    	BYTE					*b;
    }pData;
    //---------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------
    CCpuLoad::CCpuLoad()
    {
    	CpuInit();
    }
    //---------------------------------------------------------------------------------------
    
    CCpuLoad::~CCpuLoad()
    {
        CpuExit();
    }
    //---------------------------------------------------------------------------------------
    //*****************************************************************************
    //*
    //*		CpuUpdate
    //*
    //*****************************************************************************
    //	Holt die neuesten Daten für die CPU-Auslastung
    //	Ergibt 1 wenn ok sonst 0
    int CCpuLoad::UpdateCpu()
    {
    	DWORD dwSize;
    	int iError;
    	unsigned u;
    	union
    	{
    		PERF_OBJECT_TYPE		*o;
    		BYTE					*b;
    	}pType;
    	union
    	{
    		PERF_COUNTER_DEFINITION	*o;
    		BYTE					*b;
    	}pCounter;
    	union
    	{
    		PERF_INSTANCE_DEFINITION*o;
    		BYTE					*b;
    	}pInstance;
    	union
    	{
    		PERF_COUNTER_BLOCK		*o;
    		BYTE					*b;
    	}pBlock;
    
    	for(;;)
    	{
    		dwSize = dwDataSize;
    		iError = RegQueryValueEx( HKEY_PERFORMANCE_DATA, "238", 0, 0,pData.b,&dwSize);
    
    		if( iError != ERROR_MORE_DATA )
    			break;
    		dwDataSize += 256;
    
    		if( pData.o )
    			delete pData.o;
    		pData.b = new BYTE[dwDataSize];
    	}
    
    	if( iError != ERROR_SUCCESS || !pData.o )
    	{
    		if( pData.o )
    			delete pData.o;
    		return 0;
    	}
    
    	pType.b = ( (BYTE*)pData.o ) + pData.o->HeaderLength;
    
    	for( u = 0; u < pData.o->NumObjectTypes; u++ ) 
    	{
    		if( pType.o->ObjectNameTitleIndex == PROCESSOR_IDX )
    			break;
    		pType.o += pType.o->TotalByteLength;
    	}
    
    	if( u >= pData.o->NumObjectTypes )
    	{
    		delete pData.o;
    		return 0;
    	}
    
    	if( ! uCpuCount && pType.o->NumInstances > (int) uCpuCount )
    	{
    		uCpuCount = pType.o->NumInstances;
    		pCounterAct  = new __int64[uCpuCount*2];
    		pCounterPre = pCounterAct+uCpuCount;
    	}
    
    	pCounter.b = pType.b + pType.o->HeaderLength;
    
    	for( u = 1; u < pType.o->NumCounters; u++ )
    	{
    		if( pCounter.o->CounterNameTitleIndex == CPU_USAGE_IDX )
    			break;
    		pCounter.b += pCounter.o->ByteLength;
    	}
    
    	if( u >= pType.o->NumCounters )
    	{
    		delete pData.o;
    		return 0;
    	}
    
    	pInstance.b = pType.b + pType.o->DefinitionLength;
    
    	for( u = 0; (int) u < pType.o->NumInstances; u++ )
    	{
    		pBlock.b = pInstance.b + pInstance.o->ByteLength;
    
    		pCounterPre[u] = pCounterAct[u];
    		pCounterAct [u] =* (__int64*)( pBlock.b + pCounter.o->CounterOffset );
    		pInstance.b = pBlock.b + pBlock.o->ByteLength;
    	}
    
    	iSysTimePre = iSysTimeAct;
    	SystemTimeToFileTime(&pData.o->SystemTime,(LPFILETIME)&iSysTimeAct);
    
    	if( iSysTimePre == iSysTimeAct )
    		iSysTimeAct++;
    
    	return 1;
    }
    //---------------------------------------------------------------------------------------
    //*****************************************************************************
    //*
    //*		CpuInit
    //*
    //*****************************************************************************
    //	Initialisiert die CPU-Auslastungsberechnung
    //	Ergibt 1 wenn ok sonst 0
    int CCpuLoad::CpuInit()
    {
    	DWORD dwVersion;
    
    	dwVersion = GetVersion();
    	dwVersion = ( ( dwVersion & 0xFF00 ) >> 8 ) | ( ( dwVersion & 0x00FF ) << 8 );
    
    	if( dwVersion >= 0x0500 || dwVersion == 0x0400 || dwVersion == 0x0300 )
    		bIsWinNt = TRUE;
    
    	if(!UpdateCpu())
    		return 0;
    
    	return 1;
    }
    //---------------------------------------------------------------------------------------
    //*****************************************************************************
    //*
    //*		CpuExit
    //*
    //*****************************************************************************
    //	Gibt alle Speicherbereiche wieder frei
    //	Ergibt 1 wenn ok sonst 0
    int CCpuLoad::CpuExit()
    {
    
    	dwDataSize = 0;
    	uCpuCount  = 0;
    
    	if(pCounterAct)
    	{
    		delete pCounterAct;
    		pCounterAct = 0;
    		pCounterPre = 0;
    	}
    	if( pData.b )
    	{
    		delete pData.b;
    		pData.b = 0;
    	}
    	if( hWin9xKey )
    	{
    		int		iError;
    		HKEY	hKey;
    		DWORD	dwSize,dwType;
    
    		RegCloseKey(hWin9xKey);
    		hWin9xKey = 0;
    
    	    iError=RegOpenKeyEx(HKEY_DYN_DATA,"PerfStats\\StopStat",0,KEY_ALL_ACCESS,&hKey);
    
    		if( iError != ERROR_SUCCESS )
    			return 0;
    
    		dwSize = sizeof(DWORD);
    
    		RegQueryValueEx(hKey,"KERNEL\\CPUUsage",0,&dwType,(LPBYTE)&dwWin9xUsage,&dwSize);
    		RegCloseKey(hKey);
    	}
    
    	return 1;
    }
    //---------------------------------------------------------------------------------------
    //*****************************************************************************
    //*
    //*		CpuLoad
    //*
    //*****************************************************************************
    //	Ergibt die aktuelle CPU-Auslastung (0 bis 1024)
    //
    //	uCpu	: Ist die Nummer der CPU
    //
    //	Danmit das funktioniert muss zuvor eine Zeit gewartet werden
    //	und CpuUpdate aufgerufen werden
    //	z.B.	Sleep(1000);
    //			CpuUpdate();
    //			CpuLoad(0);
    //			CpuLoad(1);
    //			...
    int CCpuLoad::GetCpuLoad(unsigned uCpu)
    {
    	__int64	iValue;
    	int		iLoad;
    
    	if(uCpu>=uCpuCount)
    		return -1;
    
    	if(!bIsWinNt)									// Windows 95/98
    	{
    		if(!hWin9xKey)
    			return -1;
            iLoad = (dwWin9xUsage<<10) / 100;
    	}
    	else
    	{											// Windows NT/2000/XP
    		iValue   = pCounterAct[uCpu] - pCounterPre[uCpu];
    		iValue <<= 10;
    		iValue  /= iSysTimeAct - iSysTimePre;
    
    		iLoad    = 1024 - (int) iValue;
    	}
    
    	if( iLoad < 0 )
    		iLoad=0;
    	if( iLoad > 1024 )
    		iLoad = 1024;
    
    	return iLoad;
    }
    //---------------------------------------------------------------------------------------
    //*****************************************************************************
    //*
    //*		CpuCount
    //*
    //*****************************************************************************
    //	Gibt die Anzah aller CPU's
    int CCpuLoad::GetCpuCount()
    {
    	SYSTEM_INFO		sInfo;
    
    	if(!uCpuCount)
    		CpuInit();
    
    	GetSystemInfo(&sInfo);
    	if( uCpuCount < sInfo.dwNumberOfProcessors )
    		return uCpuCount;
    
    	return sInfo.dwNumberOfProcessors;
    }
    //---------------------------------------------------------------------------------------
    //---------------------------------------------------------------------------------------
    


  • also ich bekomme bei GetCPUCount definitiv immer nur 2 raus, obwohl ich nen quadcore hab..
    hat jemand nen link zu der sache mit wmi?



  • Was für Betriebssystem hast Du?
    Je nach BS kann es sein, daß es nur 2 CPUs unterstützt...



  • sorry, das hätte ich natürlich schreiben können 😉 das ist vista 32bit. im taskmanager wird die last jedes einzelnen cores angezeigt. iwi muss es also gehen 😉



  • Ich behaupte mal, die Anweisung in CCpuLoad::GetCpuCount()

    if( uCpuCount < sInfo.dwNumberOfProcessors )
            return uCpuCount;
    

    ist vermutlich der Übeltäter, daß als Ergebnis weniger als die tatsächliche CPU-Anzahl angegeben wird.

    Martin



  • Mmacher schrieb:

    Was für Betriebssystem hast Du?
    Je nach BS kann es sein, daß es nur 2 CPUs unterstützt...

    Welches BS unstützt denn bitte, wenn es schon 2 CPU's unterstützt, keine 4? (rhetorisch 🤡 )
    Das ziehlt doch eh aufs Multitasking/Multithreading, was Windows ja nun schon n bissl länger kann 😉 .



  • CodeFinder schrieb:

    Welches BS unstützt denn bitte, wenn es schon 2 CPU's unterstützt, keine 4? (rhetorisch 🤡 )

    Schon klar, rein rhetorisch 😉 .
    Lösung: Im Prinzip alle BS auf der WinNT-Schiene.
    Hinweis: Oft stehen sogar auf den Aufklebern mit den Seriennummern der Zusatz "1-2 CPU", insbesondere in Verbindung mit Win2000 Pro.

    Warum? Das sind einfach marketingpolitische Abstufungen seitens Mikrosoft: "Wer mehr CPUs nutzen möchte, soll bitteschön die höherwertigen Editionen kaufen."
    Oder auf marketingdeutsch: "skalierbare Lösungen" 🙄
    Beispiel: WinServer2003 Datacenter kann bis 32 CPUs unterstützen (bzw. 64 CPUs in der x64-Edition), WinServer2003 Standard kann 4 CPUs, WinServer2003 Web dagegen nur Dual CPUs.
    Früher (auf jeden Fall bis Win2000) war Anzahl CPU = Anzahl Cores, heute (z.B. Vista) ist Anzahl CPU = Anzahl physikalischer Prozessoren, unabhängig von der Core-Anzahl des jeweiligen Prozessors.

    Übrigens, das gleiche Phänomen kannst Du auch bei der nutzbaren RAM-Verwertung beobachten, guck Dir die aktuell verschiedenen Vista-Editionen an (Link habe ich nicht parat), sie können je nach Edition vershieden stark die CPUs und RAMs nutzen.

    Martin


Anmelden zum Antworten