C语言获取CPU主频并通过rdtsc获取系统时戳

#include<stdio.h>
#include<stdlib.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/time.h>

static unsigned long long rdtsc(void)
{
    unsigned int low, high;
    asm volatile ("rdtsc" : "=a"(low), "=d"(high) : );
    return ((unsigned long long)high<<32) + (unsigned long long)low;
}

unsigned long long g_startRdtsc;
struct timeval g_tvStart;
unsigned long long g_cpuCyclesMhz;
unsigned long long getCpuCyclesMhz()
{
    FILE *fp;
    char cycleStr[128];
    memset(cycleStr, 0, 128);
    fp = popen("cat /proc/cpuinfo | grep MHz | uniq |sed -e 's/.*:[^0-9]//'","r");
    if (fp<0) {
        printf("Can't read CPU cycle info !!!\n");
        exit(1);
    }
    fgets(cycleStr, 127, fp);
    fclose(fp);
    unsigned long long cycle = (unsigned long long)atof(cycleStr);
    printf("CPU cycle : %llu MHz\n", cycle);
    return cycle;
}
void myGettimeofday(struct timeval* tmValue)
{
    unsigned long long tm = rdtsc();
    tmValue->tv_sec = g_tvStart.tv_sec + (tm - g_startRdtsc)/(g_cpuCyclesMhz*1000000);
    tmValue->tv_usec= g_tvStart.tv_usec + ((tm - g_startRdtsc)/g_cpuCyclesMhz) % 1000000);
}

int main()
{
    unsigned long long tscStart[100], tscEnd[100];
    unsigned long long wrapperStart[100], wrapperEnd[100];
    struct timeval tvStart, tvEnd;
    g_startRdtsc = rdtsc();
    gettimeofday(&g_tvStart, NULL);
    g_cpuCyclesMhz = getCpuCyclesMhz();
    printf("Current machine cycles %llu\n", g_cpuCyclesMhz);
    int i;
    for (i = 0; i < 100; i++) {
        tscStart[i] = rdtsc();
        gettimeofday(&tvStart, NULL);
        tscEnd[i] = rdtsc();
    }
    for (i = 0; i < 100; i++) {
        wrapperStart[i] = rdtsc();
        myGettimeofday(&tvStart);
        wrapperEnd[i] = rdtsc();
    }
  
    for (i = 0; i < 100; i++) {
        printf("cycles gettimeofday[%d] %d myGettimeofday %d\n", i, tscEnd[i] - tscStart[i], wrapperEnd[i] - wrapperStart[i]);
    }

}

测试下优化效果几乎没有,主要耗时计算在乘除运算中,需要从使用角度优化;如果除了乘法运算,cycle耗时可以减半;

posted @ 2021-03-29 20:06  Xuperior  阅读(857)  评论(0编辑  收藏  举报