65.9K
CodeProject 正在变化。 阅读更多。
Home

CPUTest

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (19投票s)

2001 年 4 月 19 日

CPOL

2分钟阅读

viewsIcon

244983

downloadIcon

3614

一个简单的类,用于计算 CPU 频率(MHz)

<!-- 下载链接 --><!-- 文章图片 -->

Sample Image - CPUTest.gif

<!-- 在这里添加你的 HTML 代码 -->

引言

CPUTest 只是一个包含几个 static 成员函数的简单类 (CCPU)。它计算 CPU 的频率,用时 50 毫秒

工作原理

这个想法很简单,并且已经被多次实现。所有现代处理器 (Pentium+) 都有一个时间戳计数器 (TSC),它每时钟周期递增一次。读取 TSC,延迟一段时间,再次读取 TSC,并获得两个时间戳的差值 (结果以时钟周期为单位)。将周期数除以延迟时间,即可得到频率。

令人惊艳之处

大多数获取 CPU MHz 的实现都使用 Sleep() 进行延迟。Sleep() 的问题在于它的精度不高,尤其是在用于小延迟时。为了获得合理的结果,你必须至少延迟 1000 毫秒。
为了克服这个问题,我使用了 QueryPerformanceFrequency()QueryPerformanceCounter() 函数。
请查看这个函数,它是 CCPU 的一个私有成员。

// Delays for the specified amount of milliseconds
static	void	_Delay(unsigned int ms)
{
   LARGE_INTEGER	freq, c1, c2;
	__int64		x;

   // Get High-Res Timer frequency
	if (!QueryPerformanceFrequency(&freq))	
		return;
		
	// Convert ms to High-Res Timer value
	x = freq.QuadPart/1000*ms;		

   // Get first snapshot of High-Res Timer value
	QueryPerformanceCounter(&c1);		
	do
	{
            // Get second snapshot
	    QueryPerformanceCounter(&c2);	
	}while(c2.QuadPart-c1.QuadPart < x);
	// Loop while (second-first < x)	
}

这个延迟函数即使对于较短的时间段也相当准确。
此外,还有一个 _DelayOverhead() 函数,它被 GetMHz() (见下文) 使用来计算调用此函数的开销,并将其从结果中减去。
此外,GetMHz() (见下文) 函数能够更改进程优先级类和线程优先级,以便结果更准确。完成操作后,它会将 PC 和 TP 恢复到以前的设置。
由于以上所有原因,只需调用一次 GetMHz() 即可获得 CPU 的 MHz,并且完成时间仅需 50 毫秒!

//
int mhz = CCPU::GetMHz();
//

CCPU 类函数

只有一个类,即 CCPU 类。它只包含 static 成员函数,不包含任何数据。
功能包括

// The TSC is 64 bit. This function returns the low part
static unsigned int ReadTimeStampCounterLow();

// This returns the high part
static unsigned int ReadTimeStampCounterHigh();

// Returns the TSC, as an unsigned __int64
static unsigned __int64 ReadTimeStampCounter();

// Puts TSC in uHigh and uLow
static void ReadTimeStampCounter(unsigned int *uHigh, unsigned int *uLow);

// This will call the function 'func' with parameter 'param' and 
// return the difference in clock cycles.
// 'func' must be a pointer to function of this type: 
// void my_func(unsigned int param);
static __int64 GetCyclesDifference(CCPU_FUNC func, unsigned int param);

//
// Returns the MHz of the CPU
//
// Parameter             Description
// ------------------    ---------------------------------------------------
//    uTimes             The number of times to run the test. The function
//                       runs the test this number of times and returns the
//                       average. Defaults to 1.
//    uMsecPerTime       Milliseconds each test will run. Defaults to 50.
//    nThreadPriority    If different than THREAD_PRIORITY_ERROR_RETURN,
//                       it will set the current thread's priority to
//                       this value, and will restore it when the tests
//                       finish. Defaults to THREAD_PRIORITY_TIME_CRITICAL.
//    dwPriorityClass    If different than 0, it will set the current
//                       process's priority class to this value, and will
//                       restore it when the tests finish.
//                       Defaults to REALTIME_PRIORITY_CLASS.
//
// Notes
// -------------------------------------------------------------------------
// 1. The default parameter values should be ok.
//    However, the result may be wrong if (for example) the cache
//    is flushing to the hard disk at the time of the test.
// 2. Requires a Pentium+ class processor (RDTSC)
// 3. Requires support of high resolution timer. Most (if not all) Windows
//    machines are ok.
//
static int GetMHz(unsigned int uTimes=1, unsigned int uMsecPerTime=50, 
		int nThreadPriority=THREAD_PRIORITY_TIME_CRITICAL,
		DWORD dwPriorityClass=REALTIME_PRIORITY_CLASS);

结论

希望这段代码对您有所帮助;希望它能正常工作;-)。
另外,如果您运行演示程序,请在此处发布您的 CPU 频率和您获得的结果,尤其是在结果完全错误的情况下。

© . All rights reserved.