Chinaunix首页 | 论坛 | 博客
  • 博客访问: 576794
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2356
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-14 16:30:06

对于这篇文章本人快记不清是不是本人写的啦,如果不是本人写的,请告知本人,谢谢!即使是本人写的,也是根据Intel的源代码修改而来。

////// normal speed
#include
#include

void main( void )
{
    unsigned long ProcSpeed = 0;

    HKEY hKey;
    LONG rt = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey);
    if( ERROR_SUCCESS == rt )
    {
        unsigned long buflen = sizeof( ProcSpeed );
        RegQueryValueEx( hKey, "~MHz", NULL, NULL, (LPBYTE)&ProcSpeed, &buflen );
        RegCloseKey(hKey);
    }

    if( 0 != ProcSpeed )
        printf( "%ldMHz\n", ProcSpeed );
    else
        printf( "查询失败\n", ProcSpeed );
}

////// raw speed
#include
#include
typedef unsigned long ulong;

// 高精度计时
inline unsigned __int64 GetCycleCount()
{
    // __asm RDTSC
    __asm _emit 0x0F
    __asm _emit 0x31
    // return EDX:EAX;
}

void main( void )
{
    __int64 raw_freq = 0;
    __int64 t0,t1;
    __int64 freq  =0;            // Most current frequ. calculation
    __int64 freq2 =0;            // 2nd most current frequ. calc.
    __int64 freq3 =0;            // 3rd most current frequ. calc.
    __int64 total;               // Sum of previous three frequency calculations
    __int64 tries=0;             // Number of times a calculation has

    __int64  total_cycles=0, cycles;    // Clock cycles elapsed during test
    __int64  stamp0=0, stamp1=0;        // Time Stamp Variable for beginning and end of test
    __int64  total_ticks=0, ticks;      // Microseconds elapsed during test
    __int64 count_freq;                 // 高精度计数器频率

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

    if( !QueryPerformanceFrequency( (PLARGE_INTEGER)&count_freq ) )
    {
        printf( "ERROR: The installed hardware does not support a high-resolution performance counter\n" );
        return;
    }

    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 room for new frequency measurement
        freq2 = freq;     //

        QueryPerformanceCounter( (PLARGE_INTEGER)&t0 );
        t1 = t0;

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

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

            QueryPerformanceCounter( (PLARGE_INTEGER)&t1 );
            stamp0 = GetCycleCount();
        }
        t0 = t1;        // Reset Initial Time

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

            QueryPerformanceCounter( (PLARGE_INTEGER)&t1 );
            stamp1 = GetCycleCount();
        }

#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 = t1 - t0;
                                // 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/10 );       
                            // Hundred Thousandths of a
                            //   Ticks / ( 10 ticks/second )
                            //   = microseconds (us)

        total_ticks += ticks;
        total_cycles += cycles;

        if( ticks%count_freq > count_freq/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 )||
               (abs(3 * freq2-total) > 3 )||
               (abs(3 * freq3-total) > 3 )));   
                    // 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) >= 6 )
        freq3++;

    raw_freq = total_cycles / total_ticks;
    printf( "%ldMHz\n", raw_freq );
}

阅读(1557) | 评论(8) | 转发(0) |
给主人留下些什么吧!~~

网友评论2012-11-14 16:33:41

周星星
谢谢,panic早就说过,但我忘了补充上去,感谢您的再次提醒。

网友评论2012-11-14 16:33:21

liqi
inline unsigned __int64 GetCycleCount()
{
        __asm _emit 0x0F
        __asm _emit 0x31
}  
本以为这个是只要支持的CPU都能有效运行的。没想到在笔记本上出了问题。
在笔记本上,这个指令的计算会无故出错。
为什么呢?不确切的解答是:
笔记本电脑用的CPU内置了低功耗模式,这一模式的方法一般是降低运行频率。
当CPU进入低功耗模式的时候,工作频率和CPU的标称频率就不相同了。于是所有基于这个指令的数值运算全部出错。

网友评论2012-11-14 16:32:58

filix
请问,raw speed 是什么涵义?
我的 pm  730 1.6g用第二个程序测出来800MHz,郁闷了

网友评论2012-11-14 16:32:41

Coonix
非常感谢,呵呵

网友评论2012-11-14 16:32:25

周星星
GUN C++ 直接认识 RDTSC 指令,无需像VC++这样使用_emit。
直接 __asm__( "rdtsc" ) 就行了,如果你用 asm 函数,还可以加入更多的控制。