Phương pháp thời gian tốt nhất trong C?


80

Cách tốt nhất để xác định thời gian một phần mã có độ phân giải cao và tính di động là gì?

/* Time from here */
ProcessIntenseFunction();
/* to here. */

printf("Time taken %d seconds %d milliseconds", sec, msec);

Có một thư viện tiêu chuẩn sẽ có một giải pháp đa nền tảng không?

Câu trả lời:


137

Tôi nghĩ rằng điều này sẽ làm việc:

#include <time.h>

clock_t start = clock(), diff;
ProcessIntenseFunction();
diff = clock() - start;

int msec = diff * 1000 / CLOCKS_PER_SEC;
printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000);

10
Điều này thực sự tốt vì nó cung cấp cho bạn thời gian CPU thay vì thời gian đã trôi qua (thời gian trôi qua có thể bị ảnh hưởng bởi các quy trình khác). Chỉ cần lưu ý rằng con số 10 giây không nhất thiết có nghĩa là nó sẽ chạy trong 10 giây trôi qua, vì có thể có các cân nhắc về I / O. Điều này CHỈ đo CPU .
paxdiablo

1
Tôi đã sử dụng lần hàng trăm này và là giải pháp tốt nhất / đơn giản nhất cho câu hỏi này
Gerhard

4
bạn thậm chí có thể nhét tất cả những thứ này vào một macro nếu bạn đang định thời gian cho nhiều thứ thường xuyên: #define timing (a) start = clock (); a; diff = clock () - bắt đầu; msec = diff * 1000 / CLOCKS_PER_SEC; printf ("msecs:% d \ n", msec); và sau đó gọi: thời gian (IntenseFunc1 ())
eqzx

3
clock_t thường là dài và CLOCKS_PER_SEC là 1000000. Trong trường hợp này, chênh lệch hơn 4 giây sẽ cho bạn kết quả tràn và lạ
Begelfor

2
@paxdiablo Tôi nhận được kết quả hoàn toàn tương đương với điều này như với gettimeofday (), không chắc bạn đang nói gì ở đây.
dùng3467349

21

gettimeofday () có thể sẽ làm những gì bạn muốn.

Nếu bạn đang sử dụng phần cứng Intel, đây là cách đọc bộ đếm lệnh thời gian thực của CPU. Nó sẽ cho bạn biết số chu kỳ CPU được thực thi kể từ khi bộ xử lý được khởi động. Đây có lẽ là bộ đếm chi phí thấp nhất, chi tiết nhất mà bạn có thể nhận được để đo hiệu suất.

Lưu ý rằng đây là số chu kỳ CPU. Trên linux, bạn có thể lấy tốc độ CPU từ / proc / cpuinfo và chia để lấy số giây. Chuyển đổi này thành một đôi khá tiện dụng.

Khi tôi chạy điều này trên hộp của mình, tôi nhận được

11867927879484732
11867927879692217
mất nhiều thời gian để gọi printf: 207485

Đây là hướng dẫn của nhà phát triển Intel cung cấp rất nhiều chi tiết.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}

5

gettimeofday sẽ trả về thời gian chính xác đến từng micro giây trong độ phân giải của đồng hồ hệ thống. Bạn cũng có thể muốn xem dự án Bộ hẹn giờ độ phân giải cao trên SourceForge.



1

Nếu bạn không muốn thời gian của CPU thì tôi nghĩ thứ bạn đang tìm là cấu trúc thời gian.

Tôi sử dụng thông tin bên dưới để tính toán thời gian thực hiện:

int timeval_subtract(struct timeval *result,                                                                                                                                        
                     struct timeval end,                                                                                                                                                 
                     struct timeval start)                                                                                                                                               
{                                                                                                                                                                                   
        if (start.tv_usec < end.tv_usec) {                                                                                                                                          
                int nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;                                                                                                             
                end.tv_usec -= 1000000 * nsec;                                                                                                                                      
                end.tv_sec += nsec;                                                                                                                                                 
        }                                                                                                                                                                           
        if (start.tv_usec - end.tv_usec > 1000000) {                                                                                                                                
                int nsec = (end.tv_usec - start.tv_usec) / 1000000;                                                                                                                 
                end.tv_usec += 1000000 * nsec;                                                                                                                                      
                end.tv_sec -= nsec;                                                                                                                                                 
        }                                                                                                                                                                           

        result->tv_sec = end.tv_sec - start.tv_sec;                                                                                                                                 
        result->tv_usec = end.tv_usec - start.tv_usec;                                                                                                                              

        return end.tv_sec < start.tv_sec;                                                                                                                                           
}                                                                                                                                                                                   

void set_exec_time(int end)                                                                                                                                                         
{                                                                                                                                                                                   
        static struct timeval time_start;                                                                                                                                           
        struct timeval time_end;                                                                                                                                                    
        struct timeval time_diff;                                                                                                                                                   

        if (end) {                                                                                                                                                                  
                gettimeofday(&time_end, NULL);                                                                                                                                      
                if (timeval_subtract(&time_diff, time_end, time_start) == 0) {                                                                                                      
                        if (end == 1)                                                                                                                                               
                                printf("\nexec time: %1.2fs\n",                                                                                                                     
                                        time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));                                                                                       
                        else if (end == 2)                                                                                                                                          
                                printf("%1.2fs",                                                                                                                                    
                                        time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));                                                                                       
                }                                                                                                                                                                   
                return;                                                                                                                                                             
        }                                                                                                                                                                           
        gettimeofday(&time_start, NULL);                                                                                                                                            
}                                                                                                                                                                                   

void start_exec_timer()                                                                                                                                                             
{                                                                                                                                                                                   
        set_exec_time(0);                                                                                                                                                           
}                                                                                                                                                                                   

void print_exec_timer()                                                                                                                                                             
{                                                                                                                                                                                   
        set_exec_time(1);                                                                                                                                                           
}

0

Độ phân giải cao là tương đối ... Tôi đã xem xét các ví dụ và chúng chủ yếu phục vụ cho mili giây. Tuy nhiên đối với tôi, điều quan trọng là phải đo được từng micro giây. Tôi đã không thấy một giải pháp độc lập với nền tảng trong vài giây và nghĩ rằng một cái gì đó giống như đoạn mã dưới đây sẽ hữu ích. Tôi chỉ định thời gian trên windows vào lúc này và rất có thể sẽ thêm triển khai gettimeofday () khi làm tương tự trên AIX / Linux.

    #ifdef WIN32
      #ifndef PERFTIME
        #include <windows.h>
        #include <winbase.h>
        #define PERFTIME_INIT unsigned __int64 freq;  QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq);  unsigned __int64 startTime;  unsigned __int64 endTime;  double timeDifferenceInMilliseconds;
        #define PERFTIME_START QueryPerformanceCounter((LARGE_INTEGER *)&startTime);
        #define PERFTIME_END QueryPerformanceCounter((LARGE_INTEGER *)&endTime); timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency);  printf("Timing %fms\n",timeDifferenceInMilliseconds);
    #define PERFTIME(funct) {unsigned __int64 freq;  QueryPerformanceFrequency((LARGE_INTEGER*)&freq);  double timerFrequency = (1.0/freq);  unsigned __int64 startTime;  QueryPerformanceCounter((LARGE_INTEGER *)&startTime);  unsigned __int64 endTime;  funct; QueryPerformanceCounter((LARGE_INTEGER *)&endTime);  double timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency);  printf("Timing %fms\n",timeDifferenceInMilliseconds);}
      #endif
    #else
      //AIX/Linux gettimeofday() implementation here
    #endif

Sử dụng:

PERFTIME(ProcessIntenseFunction());

or

PERFTIME_INIT
PERFTIME_START
ProcessIntenseFunction()
PERFTIME_END
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.