/* clock.c * Retrofitted to use thread-specific timers * and to get clock information from /proc/cpuinfo * (C) R. E. Bryant, 2010 * Modified for cross-platform compatibility */ #define _GNU_SOURCE // For sched_setaffinity on Linux #include #include #include #include #ifdef _WIN32 #include #include #else #include #include #include #include typedef struct { uint64_t QuadPart; } LARGE_INTEGER; typedef void *HANDLE; #define __int64 long long #define Sleep(ms) usleep((ms) * 1000) #endif #include "clock.h" /* Use x86 cycle counter */ static unsigned cyc_hi = 0; static unsigned cyc_lo = 0; void access_counter(unsigned *hi, unsigned *lo) { uint64_t counter = __rdtsc(); *hi = (unsigned)(counter >> 32); *lo = (unsigned)counter; } void start_counter() { access_counter(&cyc_hi, &cyc_lo); } double get_counter() { unsigned ncyc_hi, ncyc_lo; access_counter(&ncyc_hi, &ncyc_lo); uint64_t start = ((uint64_t)cyc_hi << 32) | cyc_lo; uint64_t end = ((uint64_t)ncyc_hi << 32) | ncyc_lo; return (double)(end - start); } void make_CPU_busy(void) { volatile double old_tick = get_counter(); volatile double new_tick; while ((new_tick - old_tick) < 1000000000) { new_tick = get_counter(); } } #ifdef _WIN32 #define GET_TIME(dest) QueryPerformanceCounter(dest) #else static inline void GET_TIME(LARGE_INTEGER *dest) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); dest->QuadPart = (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec; } #define QueryPerformanceFrequency(freq) ((freq)->QuadPart = 1000000000) #endif double mhz(int verbose) { LARGE_INTEGER lFrequency; LARGE_INTEGER lPerformanceCount_Start; LARGE_INTEGER lPerformanceCount_End; double mhz; double fTime; __int64 _i64StartCpuCounter; __int64 _i64EndCpuCounter; #ifdef _WIN32 HANDLE hThread = GetCurrentThread(); SetThreadAffinityMask(hThread, 0x1); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); sched_setaffinity(0, sizeof(cpuset), &cpuset); #endif QueryPerformanceFrequency(&lFrequency); GET_TIME(&lPerformanceCount_Start); _i64StartCpuCounter = __rdtsc(); Sleep(200); GET_TIME(&lPerformanceCount_End); _i64EndCpuCounter = __rdtsc(); fTime = (lPerformanceCount_End.QuadPart - lPerformanceCount_Start.QuadPart) / (double)lFrequency.QuadPart; mhz = (_i64EndCpuCounter - _i64StartCpuCounter) / (fTime * 1000000.0); if (verbose > 0) { printf("CPU频率为: %.6fMHz.\n", mhz); } return mhz; } double CPU_Factor1(void) { double result; int i, j, k; LARGE_INTEGER lStart, lEnd; LARGE_INTEGER lFrequency; double fTime; #ifdef _WIN32 HANDLE hThread = GetCurrentThread(); SetThreadAffinityMask(hThread, 0x1); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); sched_setaffinity(0, sizeof(cpuset), &cpuset); #endif QueryPerformanceFrequency(&lFrequency); GET_TIME(&lStart); start_counter(); for (i = 0; i < 100; i++) for (j = 0; j < 1000; j++) for (k = 0; k < 1000; k++) ; result = get_counter(); GET_TIME(&lEnd); fTime = (lEnd.QuadPart - lStart.QuadPart) / (double)lFrequency.QuadPart; printf("CPU计算时长为: %f", result); printf("\t %f\n", fTime); return result; } double CPU_Factor(void) { double frequency; double multiplier = 1000 * 1000 * 1000; // nano LARGE_INTEGER lFrequency; LARGE_INTEGER start, stop; int i; const int known_instructions_per_loop = 27317; int iterations = 100000000; int g = 0; double normal_ticks_per_second; double ticks; double time; double loops_per_sec; double instructions_per_loop; double ratio; double actual_freq; #ifdef _WIN32 HANDLE hThread = GetCurrentThread(); SetThreadAffinityMask(hThread, 0x1); #else cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); sched_setaffinity(0, sizeof(cpuset), &cpuset); #endif QueryPerformanceFrequency(&lFrequency); frequency = (double)lFrequency.QuadPart; GET_TIME(&start); for (i = 0; i < iterations; i++) { g++; g++; g++; g++; } GET_TIME(&stop); normal_ticks_per_second = frequency * 1000; ticks = (double)(stop.QuadPart - start.QuadPart); time = (ticks * multiplier) / frequency; loops_per_sec = iterations / (time / multiplier); instructions_per_loop = normal_ticks_per_second / loops_per_sec; ratio = instructions_per_loop / known_instructions_per_loop; actual_freq = normal_ticks_per_second / ratio; printf("Perf counter freq: %f\n", normal_ticks_per_second); printf("Loops per sec: %f\n", loops_per_sec); printf("Perf counter freq div loops per sec: %f\n", instructions_per_loop); printf("Presumed freq: %f\n", actual_freq); printf("ratio: %f\n", ratio); printf("time=%f\n", time); return ratio; }