Folosire Windows API in programe C/C++ (forum moderat)
Ovidiu Cucu
Fondator
Posts: 3778 Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:
Post
by Ovidiu Cucu » 02 Jan 2012, 15:45
Intrebare
Cum aflu frecventa curenta a microprocesorului?
Raspuns
Se pot folosi functiile API
QueryPerformanceCounter si
QueryPerformanceFrequency in combinatie cu instructiune procesor
RDTSC (Read Time-Stamp Counter).
Exemplu
Code: Select all
ULONG GetCPUFrequency()
{
LARGE_INTEGER nCntFrequency;
if(!::QueryPerformanceFrequency(&nCntFrequency))
return 0; // high-resolution performance counter not supported
LARGE_INTEGER nCnt0, nCnt1;
ULONG nTs0, nTs1;
HANDLE hThread = ::GetCurrentThread();
int nPriority = ::GetThreadPriority(hThread);
::SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
::QueryPerformanceCounter(&nCnt1);
__asm
{
_emit 0x0f _asm _emit 0x31 // RDTSC
MOV nTs0, EAX
}
nCnt0.LowPart = nCnt1.LowPart;
while(((ULONG)nCnt1.LowPart - (ULONG)nCnt0.LowPart) < 300000)
{
::QueryPerformanceCounter(&nCnt1);
__asm
{
_emit 0x0f _asm _emit 0x31 // RDTSC
MOV nTs1, EAX
}
}
::SetThreadPriority(hThread, nPriority);
ULONG nCycles = nTs1 - nTs0;
ULONG nTicks = (ULONG)(nCnt1.LowPart - nCnt0.LowPart);
nTicks *= 10000;
nTicks /= (nCntFrequency.LowPart / 100);
return nCycles / nTicks; // MHz
}
Resurse
Vezi si
<< Back to Windows API Index
Ovidiu Cucu
Fondator
Posts: 3778 Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:
Post
by Ovidiu Cucu » 02 Jan 2012, 16:04
Raspuns
O metoda simpla este utilizand functia
CallNtPowerInformation .
Exemplu
Code: Select all
#include <windows.h>
#include <Powrprof.h>
#include <iostream>
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION;
#pragma comment(lib, "Powrprof.lib")
int main()
{
PROCESSOR_POWER_INFORMATION ppi = {0};
::CallNtPowerInformation(ProcessorInformation, NULL, 0, &ppi, sizeof(PROCESSOR_POWER_INFORMATION));
std::cout << "Current processor frequency: "
<< ppi.CurrentMhz << " MHz" << std::endl;
system("pause");
return 0;
}
Note
Exemplul de mai sus functioneaza pe Windows XP. Totusi, un vechi amic a sesizat faptul ca pe versiuni mai noi de Windows, in cazul cand exista mai multe procesoare, functia CallNtPowerInformation da kix cu eroarea STATUS_BUFFER_TOO_SMALL.
Exemplul urmator corecteaza aceasta greseala:
Code: Select all
#include <NTstatus.h>
#define WIN32_NO_STATUS
#include <windows.h>
#include <Powrprof.h>
#include <iostream>
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
#pragma comment(lib, "Powrprof.lib")
int main()
{
SYSTEM_INFO si = {0};
::GetSystemInfo(&si);
const int size = si.dwNumberOfProcessors * sizeof(PROCESSOR_POWER_INFORMATION);
LPBYTE pBuffer = new BYTE[size];
NTSTATUS status = ::CallNtPowerInformation(ProcessorInformation, NULL, 0, pBuffer, size);
if(STATUS_SUCCESS == status)
{
PPROCESSOR_POWER_INFORMATION ppi = (PPROCESSOR_POWER_INFORMATION)pBuffer;
for(DWORD nIndex = 0; nIndex < si.dwNumberOfProcessors; nIndex++)
{
std::cout << "Processor #" << ppi->Number << " frequency: "
<< ppi->CurrentMhz << " MHz" << std::endl;
ppi++;
}
}
else
{
std::cout << "CallNtPowerInformation failed. Status: " << status << std::endl;
}
delete []pBuffer;
system("pause");
return status;
}
In general ma stradui sa testez exemplele inainte de a le posta. Totusi, ca peste tot, nu este exclus sa scape erori/omisiuni/greseli. Cand apar, va rog sa le sesizati in forum.
Thank you!
Resurse
<< Back to Windows API Index