Best timing method in C?

前端 未结 6 957
广开言路
广开言路 2020-11-28 18:55

What is the best way to time a code section with high resolution and portability?

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

printf(\"Tim         


        
相关标签:
6条回答
  • 2020-11-28 19:12

    gettimeofday() will probably do what you want.

    If you're on Intel hardware, here's how to read the CPU real-time instruction counter. It will tell you the number of CPU cycles executed since the processor was booted. This is probably the finest-grained, lowest overhead counter you can get for performance measurement.

    Note that this is the number of CPU cycles. On linux you can get the CPU speed from /proc/cpuinfo and divide to get the number of seconds. Converting this to a double is quite handy.

    When I run this on my box, I get

    11867927879484732
    11867927879692217
    it took this long to call printf: 207485
    

    Here's the Intel developer's guide that gives tons of detail.

    #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);
    }
    
    0 讨论(0)
  • 2020-11-28 19:13

    High resolution is relative... I was looking at the examples and they mostly cater for milliseconds. However for me it is important to measure microseconds. I have not seen a platform independant solution for microseconds and thought something like the code below will be usefull. I was timing on windows only for the time being and will most likely add a gettimeofday() implementation when doing the same on 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
    

    Usage:

    PERFTIME(ProcessIntenseFunction());
    
    or
    
    PERFTIME_INIT
    PERFTIME_START
    ProcessIntenseFunction()
    PERFTIME_END
    
    0 讨论(0)
  • 2020-11-28 19:16

    I think this should work:

    #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);
    
    0 讨论(0)
  • 2020-11-28 19:22

    gettimeofday will return time accurate to microseconds within the resolution of the system clock. You might also want to check out the High Res Timers project on SourceForge.

    0 讨论(0)
  • 2020-11-28 19:25

    I use SDL_GetTicks from the SDL library.

    0 讨论(0)
  • 2020-11-28 19:32

    If you don't want CPU time then I think what you're looking for is the timeval struct.

    I use the below for calculating execution time:

    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 讨论(0)
提交回复
热议问题