2011-03-23 44 views
15

Tôi có mã sau đây đang chạy trên các phiên bản mẫu qnx.Đang chuyển clock_gettime sang các cửa sổ

#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; 
} 

Bây giờ tôi muốn chuyển mã trên lên cửa sổ. bất kỳ ai có thể cung cấp mã mẫu.

Cảm ơn!

+1

kiểm tra một số tùy chọn tại http://stackoverflow.com/questions/275004/c-timer-function-to-provide-time-in-nano-seconds – pmg

Trả lời

31

Bạn có thể thực hiện một sự thay thế clock_gettime() cho các cửa sổ như sau:

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); 
} 
+0

whow ... Bạn đã có sẵn mã này, đã có bạn? Tôi thích ý tưởng chỉ chiếm đoạt hàm 'clock_gettime'. – xtofl

+0

Có --- đây là mã tôi đã viết như một phần của một cổng của lmbench cho Windows –

+2

Cảm ơn đoạn mã đó. Tôi nhận được một lỗi 'không thể chuyển đổi' timespec * 'thành' timeval * 'cho đối số' 2 'thành' int clock_gettime (int, timeval *) 'khi cố gắng để crosscompile mã của bạn bằng cách sử dụng' mingw' .. tôi thiếu gì ở đây? – a1337q

8

Tránh PerformanceCounter mớ hỗn độn, mã đơn giản:

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; 
} 

... là giải pháp nhanh chóng, đáng tin cậy và chính xác porting khi độ chính xác cao không quan trọng lắm.

Và QPC dựa trên giải pháp với độ chính xác đầy đủ là:

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; 
} 
+4

Tài liệu cho cấu trúc FILETIME [ở đây] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284.aspx) nói "Không được đưa con trỏ tới cấu trúc FILETIME đến ULARGE_INTEGER * hoặc __int64 * giá trị vì nó có thể gây ra lỗi liên kết trên Windows 64 bit. " – Spencer

+0

Bạn là một vị cứu tinh. Đây là điều duy nhất đứng giữa máy Windows của tôi và thư viện C99 được nhắm mục tiêu theo Linux :) –

+1

@Spencer nó & __ int64 được truyền tới FILETIME *, không phải hướng mờ, vì vậy không phải lúc nào cũng liên kết tốt đến 8 byte. –

-1

Bạn có thể sử dụng để thực hiện timespec_get clock_gettime đơn giản.
(timespec_get chức năng có sẵn từ C11)

int clock_gettime(int, struct timespec *tv) 
{ 
    return timespec_get(tv, TIME_UTC); 
} 

... nhưng kết quả TIMESPEC có độ phân giải khoảng 10 mili giây trên máy windows7 64bit của tôi. :(

Đây là phiên bản của tôi về 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; 
} 
+1

timespec_get() không có sẵn trong VS 2013, Windows 8. –

2

tôi cải thiện phiên bản của clock_gettime() sử dụng QueryPerformanceCounter().

#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; 
} 

Tôi nghĩ rằng phiên bản của tôi là một sự cải tiến so với câu trả lời chấp nhận hiện nay sử dụng QueryPerformanceCounter(), bởi vì -

  1. Mạnh mẽ hơn - kiểm tra giá trị trả về của hàm, còn giá trị được trả lại trong biến vượt qua tham chiếu.
  2. Mạnh mẽ hơn - kiểm tra tính hợp lệ của thông số đầu vào.
  3. Được sắp xếp hợp lý hơn - Sử dụng ít nhất số lượng biến cần thiết (3 so với 7).
  4. Được sắp xếp hợp lý hơn - Tránh đường dẫn mã liên quan đến GetSystemTimeAsFileTime() từ QueryPerformanceFrequency()QueryPerformanceCounter() được đảm bảo hoạt động trên các hệ thống chạy Windows XP trở lên.
+0

Điều này không biên dịch với trình biên dịch MSVC2015. Bạn đã quên thêm tất cả các gói của mình chưa? Tôi muốn thử điều này nếu có thể. –

+1

Tôi đã không hiển thị các bao gồm trong đoạn mã nhưng nó yêu cầu tiêu đề được đề cập ở đây - https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx . –

+0

Tuyệt vời! Ty cho bản cập nhật, work.bin! Tôi sẽ kiểm tra nó ra^_^ –

Các vấn đề liên quan