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耗时可以减半;