Легко измерить прошедшее время - PullRequest
258 голосов
/ 11 мая 2010

Я пытаюсь использовать time () для измерения различных точек моей программы.

Что я не понимаю, так это то, почему значения до и после одинаковы?Я понимаю, что это не лучший способ для профилирования моей программы, я просто хочу посмотреть, как долго что-то займет.

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

Я пытался:

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

Как мне прочитать результат **time taken = 0 26339?Означает ли это, что 26339 наносекунд = 26,3 мсек?

Как насчет **time taken = 4 45025, это значит 4 секунды и 25 мсек?

Ответы [ 23 ]

258 голосов
/ 11 мая 2010
#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

Функция time() точна только с точностью до секунды, но в течение секунды CLOCKS_PER_SEC "часы". Это простое портативное измерение, даже если оно чрезмерно упрощено.

249 голосов
/ 24 февраля 2014

Вы можете абстрагировать механизм измерения времени и измерять время выполнения каждого вызываемого объекта с помощью минимальный дополнительный код , просто вызывая его через структуру таймера. Кроме того, во время компиляции вы можете параметризовать тип синхронизации (миллисекунды, наносекунды и т. Д.).

Благодаря обзору Loki Astari и предложению использовать вариадические шаблоны. Это , поэтому переадресованный вызов функции.

#include <iostream>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F&& func, Args&&... args)
    {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                            (std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

int main() {
    std::cout << measure<>::execution(functor(dummy)) << std::endl;
}

Демо

Согласно комментарию Говарда Хиннанта лучше не выходить из системы хронографа, пока нам не придется. Таким образом, приведенный выше класс может дать пользователю возможность вызвать count вручную, предоставив дополнительный статический метод (показан в C ++ 14)

template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
    auto start = std::chrono::steady_clock::now();
    std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
    return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
} 

// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;

и быть наиболее полезным для клиентов,

"хотите обработать несколько периодов до ввода / вывода (например, в среднем)"


Полный код можно найти здесь . Моя попытка построить инструмент для бенчмаркинга на основе хронографа записана здесь .


Если C ++ 17 std::invoke доступен, вызов вызываемого в execution может быть выполнен следующим образом:

invoke(forward<decltype(func)>(func), forward<Args>(args)...);

для обеспечения вызовов, которые являются указателями на функции-члены.

232 голосов
/ 02 января 2015
//***C++11 Style:***
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end= std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() <<std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() <<std::endl;
56 голосов
/ 11 мая 2010

Как видно из вашего вопроса, похоже, что вы хотите узнать, сколько времени прошло после выполнения некоторого фрагмента кода. Я думаю, вам будет удобно увидеть результаты в секундах. Если это так, попробуйте использовать функцию difftime(), как показано ниже. Надеюсь, это решит вашу проблему.

#include <time.h>
#include <stdio.h>

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );
31 голосов
/ 11 мая 2010

Только для Windows: (Тег Linux был добавлен после того, как я опубликовал этот ответ)

Вы можете использовать GetTickCount () , чтобы получить количество миллисекунд, прошедших с момента запуска системы.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();
13 голосов
/ 11 мая 2010

функция времени (NULL) возвращает количество секунд, прошедших с 01.01.1970 в 00:00. И потому, что эта функция вызывается в разное время в вашей программе, она всегда будет отличаться Время в C ++

12 голосов
/ 11 мая 2010

time(NULL) возвращает количество секунд, прошедших с 01.01.1970 в 00:00 ( Эпоха ). Таким образом, разница между двумя значениями - это количество секунд, затраченное на обработку.

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

Более точные результаты можно получить с помощью getttimeofday(), который возвращает текущее время в секундах, как time(), а также в микросекундах.

11 голосов
/ 03 июня 2016
struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

Использование ниже ::

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

Это похоже на RAII по объему

ПРИМЕЧАНИЕ: это не мое, но я подумал, что это уместно здесь

9 голосов
/ 15 сентября 2012
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 
8 голосов
/ 11 мая 2010

Значения, напечатанные вашей второй программой, представляют собой секунды и микросекунды.

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs
...