我有以下代码在qnx momemntics上运行。
#define BILLION 1000000000L; struct timespec start_time; struct timespec stop_time; void start MyTestFunc() { //Initialize the Test Start time clock_gettime(CLOCK_REALTIME,&start_time) // ... additonal code. cout << "The exectuion time of func "<< calculateExecutionTime(); } double calculateExecutionTime () { clock_gettime(CLOCK_REALTIME,&stop_time); double dSeconds = (stop_time.tv_sec - start_time.tv_sec); double dNanoSeconds = (double)( stop_time.tv_nsec - start_time.tv_nsec ) / BILLION; return dSeconds + dNanoSeconds; }
现在我想将上面的代码移植到Windows。 任何人都可以提供示例代码。
谢谢!
您可以按如下所示实现windows的clock_gettime()替换:
LARGE_INTEGER getFILETIMEoffset() { SYSTEMTIME s; FILETIME f; LARGE_INTEGER t; s.wYear = 1970; s.wMonth = 1; s.wDay = 1; s.wHour = 0; s.wMinute = 0; s.wSecond = 0; s.wMilliseconds = 0; SystemTimeToFileTime(&s, &f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; t.QuadPart |= f.dwLowDateTime; return (t); } int clock_gettime(int X, struct timeval *tv) { LARGE_INTEGER t; FILETIME f; double microseconds; static LARGE_INTEGER offset; static double frequencyToMicroseconds; static int initialized = 0; static BOOL usePerformanceCounter = 0; if (!initialized) { LARGE_INTEGER performanceFrequency; initialized = 1; usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); if (usePerformanceCounter) { QueryPerformanceCounter(&offset); frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; } else { offset = getFILETIMEoffset(); frequencyToMicroseconds = 10.; } } if (usePerformanceCounter) QueryPerformanceCounter(&t); else { GetSystemTimeAsFileTime(&f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; t.QuadPart |= f.dwLowDateTime; } t.QuadPart -= offset.QuadPart; microseconds = (double)t.QuadPart / frequencyToMicroseconds; t.QuadPart = microseconds; tv->tv_sec = t.QuadPart / 1000000; tv->tv_usec = t.QuadPart % 1000000; return (0); }
避免PerformanceCounter混乱,简单的代码:
struct timespec { long tv_sec; long tv_nsec; }; //header part int clock_gettime(int, struct timespec *spec) //C-file part { __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); wintime -=116444736000000000i64; //1jan1601 to 1jan1970 spec->tv_sec =wintime / 10000000i64; //seconds spec->tv_nsec =wintime % 10000000i64 *100; //nano-seconds return 0; }
高精度并不重要时,快速,可靠和正确的移植解决方案。
基于QPC的全解决方案是:
struct timespec { long tv_sec; long tv_nsec; }; //header part #define exp7 10000000i64 //1E+7 //C-file part #define exp9 1000000000i64 //1E+9 #define w2ux 116444736000000000i64 //1.jan1601 to 1.jan1970 void unix_time(struct timespec *spec) { __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); wintime -=w2ux; spec->tv_sec =wintime / exp7; spec->tv_nsec =wintime % exp7 *100; } int clock_gettime(int, timespec *spec) { static struct timespec startspec; static double ticks2nano; static __int64 startticks, tps =0; __int64 tmp, curticks; QueryPerformanceFrequency((LARGE_INTEGER*)&tmp); //some strange system can if (tps !=tmp) { tps =tmp; //init ~~ONCE //possibly change freq ? QueryPerformanceCounter((LARGE_INTEGER*)&startticks); unix_time(&startspec); ticks2nano =(double)exp9 / tps; } QueryPerformanceCounter((LARGE_INTEGER*)&curticks); curticks -=startticks; spec->tv_sec =startspec.tv_sec + (curticks / tps); spec->tv_nsec =startspec.tv_nsec + (double)(curticks % tps) * ticks2nano; if (!(spec->tv_nsec < exp9)) { spec->tv_sec++; spec->tv_nsec -=exp9; } return 0; }
我使用QueryPerformanceCounter()
改进了clock_gettime()
版本。
#define BILLION (1E9) static BOOL g_first_time = 1; static LARGE_INTEGER g_counts_per_sec; int clock_gettime(int dummy, struct timespec *ct) { LARGE_INTEGER count; if (g_first_time) { g_first_time = 0; if (0 == QueryPerformanceFrequency(&g_counts_per_sec)) { g_counts_per_sec.QuadPart = 0; } } if ((NULL == ct) || (g_counts_per_sec.QuadPart <= 0) || (0 == QueryPerformanceCounter(&count))) { return -1; } ct->tv_sec = count.QuadPart / g_counts_per_sec.QuadPart; ct->tv_nsec = ((count.QuadPart % g_counts_per_sec.QuadPart) * BILLION) / g_counts_per_sec.QuadPart; return 0; }
我认为我的版本是对使用QueryPerformanceCounter()
目前接受的答案的改进,因为 –
GetSystemTimeAsFileTime()
的代码路径,因为QueryPerformanceFrequency()和QueryPerformanceCounter()保证可以在运行Windows XP或更高版本的系统上运行 。 您可以使用timespec_get来实现简单的clock_gettime。
(自C11开始, timespec_get函数可用)
int clock_gettime(int, struct timespec *tv) { return timespec_get(tv, TIME_UTC); }
…但结果timespec在我的Windows7 64位机器上的分辨率约为10毫微米。 🙁
这是我的clock_gettime版本。
int clock_gettime(int, struct timespec *tv) { static int initialized = 0; static LARGE_INTEGER freq, startCount; static struct timespec tv_start; LARGE_INTEGER curCount; time_t sec_part; long nsec_part; if (!initialized) { QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&startCount); timespec_get(&tv_start, TIME_UTC); initialized = 1; } QueryPerformanceCounter(&curCount); curCount.QuadPart -= startCount.QuadPart; sec_part = curCount.QuadPart / freq.QuadPart; nsec_part = (long)((curCount.QuadPart - (sec_part * freq.QuadPart)) * 1000000000UL / freq.QuadPart); tv->tv_sec = tv_start.tv_sec + sec_part; tv->tv_nsec = tv_start.tv_nsec + nsec_part; if(tv->tv_nsec >= 1000000000UL) { tv->tv_sec += 1; tv->tv_nsec -= 1000000000UL; } return 0; }