c# - Need some help in getting the CPU Frequency -
i'm trying make c# software reads information cpu , displays them user (just cpu-z). current problem i've failed find way display cpu frequency.
at first tried easy way using win32_processor class. proved efficient, except if cpu overclocked (or underclocked).
then, discovered registry contain @ hklm\hardware\description\system\centralprocessor\0 "standard" clock of cpu (even if overclocked). problem in modern cpus, core multiplier decreasing when cpu not need it's full power, cpu frequency changing, value in registry remains same.
my next step trying use rdtsc calculate cpu frequency. used c++ because can embed in c# project if method working. found next code @ http://www.codeproject.com/articles/7340/get-the-processor-speed-in-two-simple-ways problem same: program gives me maximum frequency (like in registry value, 1-2 mhz difference) , looks loads cpu more should (i had cpu load spikes).
#include "stdafx.h" #include <windows.h> #include <cstdlib> #include "intrin.h" #include <winerror.h> #include <winnt.h> float procspeedcalc() { #define rdtsc __asm _emit 0x0f __asm _emit 0x31 // variables clock-cycles: __int64 cyclesstart = 0, cyclesstop = 0; // variables high-res preformance counter: unsigned __int64 nctr = 0, nfreq = 0, nctrstop = 0; // retrieve performance-counter frequency per second: if(!queryperformancefrequency((large_integer *) &nfreq)) return 0; // retrieve current value of performance counter: queryperformancecounter((large_integer *) &nctrstop); // add frequency counter-value: nctrstop += nfreq; _asm {// retrieve clock-cycles start value: rdtsc mov dword ptr cyclesstart, eax mov dword ptr [cyclesstart + 4], edx } do{ // retrieve value of performance counter // until 1 sec has gone by: queryperformancecounter((large_integer *) &nctr); }while (nctr < nctrstop); _asm {// retrieve again clock-cycles after 1 sec. has gone by: rdtsc mov dword ptr cyclesstop, eax mov dword ptr [cyclesstop + 4], edx } // stop-start speed in hz divided 1,000,000 speed in mhz return ((float)cyclesstop-(float)cyclesstart) / 1000000; } int _tmain(int argc, _tchar* argv[]) { while(true) { printf("cpu frequency = %f\n",procspeedcalc()); sleep(1000); } return 0; }
i should mention i've tested last method on amd cpu. i've tried other codes rdtsc method, none working correctly.
finally, i've tried understand code used make program https://code.google.com/p/open-hardware-monitor/source/browse/ , complex me.
so, question is: how determine cpu frequency in real-time (even when cpu overclocked) using c++ or c# ? know question asked lot of times, none answers question.
yes, code sits , busy-waits entire second, has causes core 100% busy second. 1 second more enough time dynamic clocking algorithms detect load , kick cpu frequency out of power-saving states. wouldn't surprised if processors boost show frequency above labelled frequency.
the concept isn't bad, however. have sleep interval of 1 second. then, instead of assuming rdtsc invocations 1 second apart, divide actual time indicated queryperformancecounter
.
also, recommend checking rdtsc
both before , after queryperformancecounter
call, detect whether there context switch between rdtsc
, queryperformancecounter
mess results.
unfortunately, rdtsc
on new processors doesn't count cpu clock cycles. doesn't reflect dynamically changing cpu clock rate (it measure nominal rate without busy-waiting, though, big improvement on code provided in question).
so looks you'd need access model-specific registers after all. can't done user-mode. the openhardwaremonitor project has both driver can used , code frequency calculations
float procspeedcalc() { /* rdtsc: it's pentium instruction "read time stamp counter". measures number of clock cycles have passed since processor reset, 64-bit number. that's <code>_emit</code> lines do. */ // microsoft inline assembler knows rdtsc instruction. no need emit. // variables cpu cycle counter (unknown rate): __int64 tscbefore, tscafter, tsccheck; // variables performance counter 9steady known rate): large_integer hpetfreq, hpetbefore, hpetafter; // retrieve performance-counter frequency per second: if (!queryperformancefrequency(&hpetfreq)) return 0; int retrylimit = 10; { // read cpu cycle count _asm { rdtsc mov dword ptr tscbefore, eax mov dword ptr [tscbefore + 4], edx } // retrieve current value of performance counter: queryperformancecounter(&hpetbefore); // read cpu cycle count again, detect context switch _asm { rdtsc mov dword ptr tsccheck, eax mov dword ptr [tsccheck + 4], edx } } while ((tsccheck - tscbefore) > 800 && (--retrylimit) > 0); sleep(1000); { // read cpu cycle count _asm { rdtsc mov dword ptr tscafter, eax mov dword ptr [tscafter + 4], edx } // retrieve current value of performance counter: queryperformancecounter(&hpetafter); // read cpu cycle count again, detect context switch _asm { rdtsc mov dword ptr tsccheck, eax mov dword ptr [tsccheck + 4], edx } } while ((tsccheck - tscafter) > 800 && (--retrylimit) > 0); // stop-start speed in hz divided 1,000,000 speed in mhz return (double)(tscafter - tscbefore) / (double)(hpetafter.quadpart - hpetbefore.quadpart) * (double)hpetfreq.quadpart / 1.0e6; }
most compilers provide __rdtsc()
intrinsic, in case use tscbefore = __rdtsc();
instead of __asm
block. both methods platform- , compiler-specific, unfortunately.
Comments
Post a Comment