⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 speed.c

📁 一个取得 CPU 信息的程序源码 可以获取16位和32位CPU的信息
💻 C
📖 第 1 页 / 共 2 页
字号:

	int tries=0;			// Number of times a calculation has
							//   been made on this call to 
							//   cpuspeed

	ulong  total_cycles=0, cycles;	// Clock cycles elapsed 
									//   during test
	
	ulong  stamp0, stamp1;			// Time Stamp Variable 
									//   for beginning and end 
									//   of test

	ulong  total_ticks=0, ticks;	// Microseconds elapsed 
									//   during test
	
	LARGE_INTEGER count_freq;		// High Resolution 
									//   Performance Counter 
									//   frequency

#ifdef WIN32
	int iPriority;
	HANDLE hThread = GetCurrentThread();
#endif // WIN32;

	memset(&cpu_speed, 0x00, sizeof(cpu_speed));

	if ( !QueryPerformanceFrequency ( &count_freq ) )
		return cpu_speed;

	// On processors supporting the Read 
	//   Time Stamp opcode, compare elapsed
	//   time on the High-Resolution Counter
	//   with elapsed cycles on the Time 
	//   Stamp Register.
	
	do {			// This do loop runs up to 20 times or
	   				//   until the average of the previous 
	   				//   three calculated frequencies is 
	   				//   within 1 MHz of each of the 
	   				//   individual calculated frequencies. 
					//   This resampling increases the 
					//   accuracy of the results since
					//   outside factors could affect this
					//   calculation
			
		tries++;		// Increment number of times sampled
						//   on this call to cpuspeed
			
		freq3 = freq2;	// Shift frequencies back to make
		freq2 = freq;	//   room for new frequency 
						//   measurement

    	QueryPerformanceCounter(&t0);	
    					// Get high-resolution performance 
    					//   counter time
			
		t1.LowPart = t0.LowPart;		// Set Initial time
		t1.HighPart = t0.HighPart;

#ifdef WIN32
		iPriority = GetThreadPriority(hThread);
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
		{
			SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
		}
#endif // WIN32

   		while ( (ulong)t1.LowPart - (ulong)t0.LowPart<50) {	  
   						// Loop until 50 ticks have 
   						//   passed	since last read of hi-
						//	 res counter. This accounts for
						//   overhead later.

			QueryPerformanceCounter(&t1);

			RDTSC;						// Read Time Stamp
			_asm {
				MOV stamp0, EAX
			}
		}
			
			
		t0.LowPart = t1.LowPart;		// Reset Initial 
		t0.HighPart = t1.HighPart;		//   Time

   		while ((ulong)t1.LowPart-(ulong)t0.LowPart<1000 ) {
   						// Loop until 1000 ticks have 
   						//   passed	since last read of hi-
   						//   res counter. This allows for
						//   elapsed time for sampling.
   			
				
   			QueryPerformanceCounter(&t1);
   			

			RDTSC;						// Read Time Stamp
			__asm {
				MOV stamp1, EAX
			}
		}

			

#ifdef WIN32
		// Reset priority
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
		{
			SetThreadPriority(hThread, iPriority);
		}
#endif // WIN32

       	cycles = stamp1 - stamp0;	// Number of internal 
        							//   clock cycles is 
        							//   difference between 
        							//   two time stamp 
        							//   readings.

    	ticks = (ulong) t1.LowPart - (ulong) t0.LowPart;	
								// Number of external ticks is
								//   difference between two
								//   hi-res counter reads.
	

		// Note that some seemingly arbitrary mulitplies and
		//   divides are done below. This is to maintain a 
		//   high level of precision without truncating the 
		//   most significant data. According to what value 
		//   ITERATIIONS is set to, these multiplies and
		//   divides might need to be shifted for optimal
		//   precision.

		ticks = ticks * 100000;	
							// Convert ticks to hundred
							//   thousandths of a tick
			
		ticks = ticks / ( count_freq.LowPart/10 );		
							// Hundred Thousandths of a 
							//   Ticks / ( 10 ticks/second )
							//   = microseconds (us)

		total_ticks += ticks;
		total_cycles += cycles;

		if ( ticks%count_freq.LowPart > count_freq.LowPart/2 )
			ticks++;			// Round up if necessary
			
		freq = cycles/ticks;	// Cycles / us  = MHz
        										
     	if ( cycles%ticks > ticks/2 )
       		freq++;				// Round up if necessary
          	
		total = ( freq + freq2 + freq3 );
							// Total last three frequency 
							//   calculations

	} while ( (tries < 3 ) || 		
	          (tries < 20)&&
	          ((abs(3 * freq -total) > 3*TOLERANCE )||
	           (abs(3 * freq2-total) > 3*TOLERANCE )||
	           (abs(3 * freq3-total) > 3*TOLERANCE )));	
					// Compare last three calculations to 
	          		//   average of last three calculations.		

	// Try one more significant digit.
	freq3 = ( total_cycles * 10 ) / total_ticks;
	freq2 = ( total_cycles * 100 ) / total_ticks;


	if ( freq2 - (freq3 * 10) >= ROUND_THRESHOLD )
		freq3++;

	cpu_speed.raw_freq = total_cycles / total_ticks;
	cpu_speed.norm_freq = cpu_speed.raw_freq;

	freq = cpu_speed.raw_freq * 10;
	if( (freq3 - freq) >= ROUND_THRESHOLD )
		cpu_speed.norm_freq++;

	cpu_speed.ex_ticks = total_ticks;
	cpu_speed.in_cycles = total_cycles;

	return cpu_speed;
}

int GetCmosTick(void)
{
	int tick = 0;

	// __asm	mov ah, 02h
	// __asm	int 1Ah
	// __asm	mov al, dh
	// __asm	and ax, 000Fh  

	__asm  xor ax, ax
	__asm  out 070h, al

	__asm  xor ax, ax
	__asm  in  al, 071h

    // _outp( 0x70, offset );
    // base = _inp( 0x71 ); 

// value returned in ax by function

	__asm 	mov word ptr tick, ax

	return tick;
}

//***************************************************************
//
// Function: cpuTimeStamp
//
//		Returns the pentium cpu time stamp in 2 32 bit unsigned longs
//
//	Notes: maintains a flag to make sure the cpu supports the RDTSC instruction.  There is
//		the overhead of checking the cpu the first time afterwhich the time consumed in 
//		checking the flag is very minimal.  You could adjust the count but then you would
//		have to do 64bit math.  ugh.
//
//***************************************************************
unsigned long cpuTimeStamp(unsigned long *hi, unsigned long *low)
{
	unsigned long ulHi = 0L;
	unsigned long ulLow = 0L;
	__asm {
		;RDTSC
		_emit 0Fh
		_emit 31h
		mov ulLow, eax
		mov ulHi, edx
	}		

	*hi = ulHi;
	*low = ulLow;

	return ulLow;		
}	


//#define ABS_TICK(a,b)  (b<a)?b+60-a:b-a
// since I am only interested in single ticks
#define ABS_TICK(a,b)  (b<a)?b+10-a:b-a

static struct FREQ_INFO GetCmosCpuSpeed()
{
	unsigned long 	t1Low, t1High, t2Low, t2High, tResLow, tResHigh;
	int	timeStart, timeStop, lapseTime;
	unsigned long   temp;
	unsigned long   temp1;
	struct FREQ_INFO cpu_speed;
	unsigned long   cpuSpeed = 0l;
#ifdef WIN32
	HANDLE	hThread = GetCurrentThread();
	int		iPriority;
#endif // WIN32
	

	memset(&cpu_speed, 0x00, sizeof(cpu_speed));

	// This loop waits for the next tick
	// so that we begin speed test on a tick edge
#ifdef WIN32
		iPriority = GetThreadPriority(hThread);
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
		{
			SetThreadPriority(hThread, iPriority+1);
		}
#endif // WIN32

	timeStart = GetCmosTick();
	for(;;)
	{
		timeStop = GetCmosTick();
		if (  ABS_TICK(timeStart,timeStop) > 0 )
		{
			cpuTimeStamp(&t1High, &t1Low);
			break;	
		}	
	}

	timeStart = timeStop;

	for(;;)
	{
		timeStop = GetCmosTick();
		if (  ABS_TICK(timeStart,timeStop) > 0 )
		{
			cpuTimeStamp(&t2High, &t2Low);
			break;	
		}	
	}

#ifdef WIN32
		// Set thread priority back.
		if ( iPriority != THREAD_PRIORITY_ERROR_RETURN )
		{
			SetThreadPriority(hThread, iPriority);
		}
#endif // WIN32

	diffTime64(t1High, t1Low, t2High, t2Low, &tResHigh, &tResLow );
	lapseTime = ABS_TICK(timeStart,timeStop);

	cpuSpeed = tResLow; ///lapseTime; 
	cpu_speed.in_cycles = tResLow;		// Cycles count since we in this routine

	//round to nearest digit
	temp =  cpuSpeed/1000000; 	
	temp1 = cpuSpeed/100000;  
	temp = temp * 10;  // realign with last digit = zero

	cpuSpeed = cpuSpeed/1000000; // cpuSpeed/1000000;
	cpu_speed.raw_freq = cpuSpeed;	

	if( (temp1 - temp) >= ROUND_THRESHOLD )
		cpuSpeed++;
	
	cpu_speed.norm_freq = cpuSpeed;	
	cpu_speed.ex_ticks = (timeStop - timeStart) * 1000000;

	return cpu_speed;			
}

//***************************************************************
//
// Function: diffTime64
//
//		Calculates the difference of a 64 bit time as represented by
//		two 32 bit unsigned longs
//
//***************************************************************
unsigned long diffTime64(unsigned long t1Hi, unsigned long t1Low, 
						 unsigned long t2Hi, unsigned long t2Low, 
 					 	 unsigned long *tHi, unsigned long *tLow )
{
	unsigned long xl, xh;

/*
	*tHi = t2Hi - t1Hi;

	if( t1Low > t2Low )
	{
		*tLow = t1Low - t2Low;
		*tLow = ULONG_MAX - *tLow; 		
		*tHi -= 1;

	} else {
		*tLow = t2Low - t1Low;
	}
*/

	__asm {
		mov eax, t2Low
		mov ebx, t1Low
		sub eax, ebx
		mov xl, eax
		mov eax, t2Hi
		mov ebx, t1Hi
		sbb eax, ebx
		mov xh, eax
	}

	*tLow = xl;
	*tHi  = xh;

	return *tLow;

}	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -