Легко измерить прошедшее время


297

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

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

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? Означает ли это, что 26,339 наносекунд = 26,3 мсек?

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


10
Я не понимаю вопроса. Конечно значения разные. Время прошло между ними, поэтому time()возвращает другое значение.
— Томас

1
Что вы имеете в виду «я не понимаю, почему значения в до и после разные»? Вы получаете текущее время (в секундах с 1 января 1970 года), используя time(NULL)... во второй раз, когда вы звоните, оно будет через N секунд после первого и, следовательно, ... другим (если вы не делаете не займет и секунды, чтобы завершить ... в этом случае это будет так же, как первый).
— Брайан Роуч

1
Можете ли вы сказать нам, что он печатает, и сколько времени это займет, если вы рассчитываете его с помощью секундомера или настенных часов (или календаря)?
— Мэтт Кертис

4
Извините, я имею в виду, что оба значения одинаковы. Я неправильно набрал свой вопрос.
— hap497

2
Смотрите эту ветку: stackoverflow.com/questions/275004/…
— умолчанию

Ответы:


336
//***C++11 Style:***
#include <chrono>

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() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;

10
да, это должен быть ответ
— Ференц Дайка

23
Для запуска этого нужно добавить #include <chrono>директиву и я хотел бы изменить время представления отчетности , как: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(и не забыть C ++ 11 флага при компиляции: -std=c++11)
— Антонелло

1
Кстати, это измеряет время процессора, а не время настенных часов. Правильно?
— Никос

4
@ RestlessC0bra Согласно документации по cppreference: «Эти часы не связаны со временем настенных часов (например, это может быть время с момента последней перезагрузки) и наиболее подходят для измерения интервалов».
— цис

1
Какой это тип данных? Std :: chrono :: duration_cast <std :: chrono :: microseconds> (конец - начало) .count ()
— sqp_125

272
#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«часы» в течение одной секунды. Это простое, портативное измерение, даже если оно чрезмерно упрощено.


129
Имейте в виду, что clock()измеряет процессорное время, а не фактическое истекшее время (которое может быть намного больше).
— Jlstrecker

12
При программировании параллельного кода для кластеров этот метод не отражает реального времени ...
— Николас Гамильтон

3
Это кажется самым простым из способов. Не хотите ли обновить комментарий или написать адрес @jlstrecker?
— Лора Атткинс

5
Вышеуказанное решение не является хорошим решением по многим причинам. Это правильный ответ - stackoverflow.com/questions/2962785/…
— Xofo

1
Я попробовал это решение, и, как показывают комментарии, мой таймер работал намного быстрее, чем в реальном времени.
— RTbecard

267

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

Благодаря обзору 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;
}

Demo

Согласно комментарию Говарда Хиннанта , лучше не выходить из системы хронографа, пока мы не должны. Таким образом, вышеприведенный класс может дать пользователю возможность 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;

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

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


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


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

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

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


2
Ницца; У меня есть что-то похожее в моем коде, но я использую другой интерфейс к классу: у меня есть class ( code_timer), который принимает время начала ( std::chrono::system_clock::now();) в конструкторе, метод, code_timer::ellapsedкоторый измеряет разницу между новым now()вызовом и тем, что в конструкторе и code_timer::resetметод, который сбрасывает время начала до нового now()результата. Чтобы измерить выполнение функтора в моем коде, я использую свободную функцию вне класса. Это позволяет измерять время от построения объекта до завершения асинхронного вызова.
— utnapistim

7
<nitpick>: не выходите из chronoсистемы, пока вам не придется (избегайте использования .count()). Пусть клиент звонит, .count()когда вынужден (скажем, для ввода / вывода, что действительно неудачно). Клиент может захотеть постобработать несколько периодов до ввода / вывода (например, в среднем), и это лучше всего сделать в chronoсистеме.
— Говард Хиннант

1
@ user3241228 1. VS2013 не поддерживает типы с автоматическим возвратом (только конечные типы с возвратом - функция C ++ 14 еще не доступна). 2. Я полагаю, что это причина, но я спросил aq просто чтобы быть уверенным
— Никос Атанасиу

2
Почему нет std::forward<F>(func)?
— oliora

3
@oliora Это то же самое. Я предпочитаю, std::forward<decltype(func)>(func)потому что он может применяться к аргументам универсального lambdas ( auto&& func), где Fнет синтаксического там, и его легко абстрагировать в служебном макросе, #define fw(arg) std::forward<decltype(arg)>(arg)который я делаю в моей библиотеке тестов (так что это синтаксический остаток, над которым я не особо разбираюсь) ответ)
— Никос Атанасиу

56

Как я вижу из вашего вопроса, похоже, что вы хотите знать, сколько времени прошло после выполнения некоторого фрагмента кода. Я полагаю, вам будет удобно увидеть результаты в секундах. Если это так, попробуйте использовать 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 );

4
Это всегда дает мне целые секунды. Это должно случиться?
— нитрат натрия

10
время всегда будет возвращать только секунды, поэтому его нельзя использовать для измерений менее секунды.
— DeepDeadpool

31

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

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

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
Я использую это на Linux. Поэтому я не могу использовать функцию GetTickCount ().
— hap497

1
уже не
— бери в

Он работает и дает реальное время, а не процессорное время. Я проверил это, поместив SleepEx(5000,0)вместо // Выполнение трудоемкой операции и разность afterи beforeсоставила почти 5 секунд.
— Ruchir

14

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()и в микросекундах.


13

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


Я не знаю, почему кто-то проголосовал, но ваш ответ не совсем правильный. Для начала он не возвращает дату и не всегда будет другим.
— Matt Joiner

12
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 по объему

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


1
в том числе пропавших
— Степан Яковенко

9
#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 

3
Хотя ваш ответ приветствуется, мы предпочитаем преамбулу, содержащую краткое описание кода. Спасибо.
— Кев

2
Это не прошедшее время, а время процессора.
— JonnyJD

8

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

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

8
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

4

C ++ std :: chrono имеет явное преимущество кроссплатформенности. Тем не менее, он также вносит значительные накладные расходы по сравнению с POSIX clock_gettime (). На моем Linux-компьютере все std::chrono::xxx_clock::now()разновидности работают примерно одинаково:

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

Хотя POSIX clock_gettime(CLOCK_MONOTONIC, &time)должен быть таким же, какsteady_clock::now() но он более чем в 3 раза быстрее!

Вот мой тест, для полноты.

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = end.tv_nsec >= start.tv_nsec
                        ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                        : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

И это вывод, который я получаю при компиляции с gcc7.2 -O3:

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds

3

time(NULL)Вызов функции возвращает количество секунд , прошедшее с момента EPOC: 1 января 1970 года Возможно , что вы имеете в виду , чтобы сделать , это взять разницу между двумя отметками:

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);

3

Как уже отмечали другие, функция time () в стандартной библиотеке C не имеет разрешения лучше одной секунды. Похоже, единственной полностью переносимой функцией C, которая может обеспечить лучшее разрешение, является clock (), но она измеряет время процессора, а не время настенных часов. Если кто-то ограничен платформой POSIX (например, Linux), то функция clock_gettime () - хороший выбор.

Начиная с C ++ 11 доступны гораздо лучшие средства синхронизации, которые предлагают лучшее разрешение в форме, которая должна быть очень переносимой для разных компиляторов и операционных систем. Точно так же библиотека boost :: datetime предоставляет хорошие классы синхронизации высокого разрешения, которые должны быть легко переносимыми.

Одной из проблем при использовании любого из этих средств является задержка, вызванная запросом системных часов. Из экспериментов с clock_gettime (), boost :: datetime и std :: chrono, эта задержка может легко составлять несколько микросекунд. Таким образом, при измерении длительности любой части вашего кода вы должны учитывать наличие ошибки измерения примерно такого размера или пытаться каким-то образом исправить эту нулевую ошибку. В идеале вам может потребоваться собрать несколько измерений времени, затраченного вашей функцией, и вычислить среднее или максимальное / минимальное время, затраченное на несколько прогонов.

Чтобы помочь решить все эти проблемы переносимости и сбора статистики, я разработал библиотеку cxx-rtimers, доступную на Github, которая пытается предоставить простой API для блоков синхронизации кода C ++, вычисления нулевых ошибок и отчетности по статистике из встроенных таймеров. в вашем коде. Если у вас есть компилятор C ++ 11, вы просто #include <rtimers/cxx11.hpp>используете что-то вроде:

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

При выходе из программы вы получите сводную статистику по времени, записанную в std :: cerr, такую ​​как:

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

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

Если вы хотите использовать специфичные для Linux функции синхронизации, вы можете #include <rtimers/posix.hpp>или, если у вас есть библиотеки Boost, но более старый компилятор C ++, вы можете это сделать #include <rtimers/boost.hpp>. Существуют также версии этих классов таймеров, которые могут собирать статистическую информацию о времени из разных потоков. Существуют также методы, позволяющие оценить нулевую ошибку, связанную с двумя непосредственно последовательными запросами системных часов.


2

Внутренне функция будет обращаться к системным часам, поэтому каждый раз, когда вы их вызываете, она возвращает разные значения. В целом, в нефункциональных языках может быть много побочных эффектов и скрытого состояния в функциях, которые вы не можете увидеть, просто взглянув на имя и аргументы функции.


2

Из того, что видно, tv_sec хранит прошедшие секунды, в то время как tv_usec хранит прошедшие отдельно микросекунды. И они не являются обращением друг друга. Следовательно, они должны быть изменены на соответствующую единицу и добавлены, чтобы получить общее время, прошедшее.

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );

2

В linux clock_gettime () - один из лучших вариантов. Вы должны связать библиотеку в реальном времени (-lrt).

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

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }

2

Мне нужно было измерить время выполнения отдельных функций в библиотеке. Я не хотел оборачивать каждый вызов каждой функции функцией измерения времени, потому что это уродливо и углубляет стек вызовов. Я также не хотел помещать код таймера вверху и внизу каждой функции, потому что он создает беспорядок, когда функция может рано выйти или выдать исключения, например. В итоге я сделал таймер, который использует свое время жизни для измерения времени.

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

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

Структура перезвонит вам по предоставленному функтору, когда он выйдет из области видимости, чтобы вы могли что-то сделать с информацией о времени (распечатать или сохранить ее или что-то еще). Если вам нужно сделать что - то еще более сложными вы можете использовать даже std::bindс std::placeholdersобратным вызовом функции с большим количеством аргументов.

Вот быстрый пример его использования:

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

Если вы хотите быть более взвешенным, вы также можете использовать newиdelete явно запускать и останавливать таймер, не полагаясь на то, что он сделает это за вас.


1

Они одинаковы, потому что ваша функция doSomething происходит быстрее, чем гранулярность таймера. Пытаться:

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

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

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

1

Причина, по которой оба значения одинаковы, заключается в том, что ваша длинная процедура не занимает столько времени - менее одной секунды. Вы можете попробовать просто добавить длинный цикл (for (int i = 0; i <100000000; i ++);) в конце функции, чтобы убедиться, что это проблема, тогда мы можем перейти оттуда ...

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


1

Я обычно использую следующее:

#include <chrono>
#include <type_traits>

using perf_clock = std::conditional<
    std::chrono::high_resolution_clock::is_steady,
    std::chrono::high_resolution_clock,
    std::chrono::steady_clock
>::type;

using floating_seconds = std::chrono::duration<double>;

template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
   const auto t0 = perf_clock::now();
   std::forward<Func>(func)(std::forward<Args>(args)...);
   return floating_seconds(perf_clock::now() - t0);
} 

Это то же самое, что предложил @ nikos-athanasiou, за исключением того, что я избегаю использования нестационарных часов и использую плавающее число секунд в качестве продолжительности.


1
На этом переключателе типов : Обычно high_resolution_clockэто typedef для либо system_clockили steady_clock. Таким образом, чтобы проследить, что std::conditionalесли is_steadyчасть истинна, тогда вы выбираете, high_resolution_clockкоторый является (typedef) steady_clock. Если это неверно, вы выбираете steady_clockснова. Просто используйте steady_clockс самого начала ...
— Никос Атанасиу

@ nikos-athanasiou Я полностью согласен с комментарием 5gon12eder о том, что «типичный» случай не требуется стандартом, поэтому некоторые STL могут быть реализованы другим способом. Я предпочитаю, чтобы мой код был более общим и не связанным с деталями реализации.
— oliora

Это не требуется , но в явном виде указано в 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. Причина заключается в следующем: high_resolution_clockпредставляет часы с самым коротким периодом тиков, поэтому, независимо от реализации, у нее есть два варианта: постоянный или нет. Какой бы выбор мы ни сделали, сказать, что реализация будет отличаться от двух других тактовых импульсов, все равно, что сказать, что у нас есть лучшая реализация для устойчивых (или нет) тактовых импульсов, которые мы решили не использовать (для устойчивых или нет тактовых генераторов). Знать, как хорошо, знать, почему лучше
— Никос Атанасиу

@ nikos-athanasiou Я бы предпочел быть на 100% безопасным, особенно когда это не стоило мне затрат времени выполнения и необнаружимых затрат времени компиляции. Вы можете положиться на «может» и предположения, если хотите.
— Олиора

В отличие от моего друга, это вы, что полагается на «май», но устраивать себя. Если вы хотите быть на 100% уверены и продолжаете писать это, вы должны также найти способ для вас и пользователей вашего кода избежать непередаваемого смешивания моментов времени разных часов (если этот тип переключателя приобретает смысл, он будет вести себя по-разному на разных платформах). Радоваться, веселиться!
— Никос Атанасиу

0

В ответ на три конкретных вопроса ОП .

«Что я не понимаю, так это то, почему значения до и после одинаковы? »

Первый вопрос и образец кода показывает , что time()имеет разрешение в 1 секунду, так что ответ должен быть , что эти две функции выполняют менее чем за 1 секунду. Но иногда это (очевидно, нелогично) сообщит 1 секунду если две метки таймера пересекают границу в одну секунду.

Следующий пример использует gettimeofday()который заполняет эту структуру

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

и второй вопрос спрашивает: «Как я могу прочитать результат **time taken = 0 26339? Означает ли это 26 339 наносекунд = 26,3 мс?»

Мой второй ответ: время составляет 0 секунд и 26339 микросекунд, то есть 0,026339 секунд, что подтверждает первый пример, выполненный менее чем за 1 секунду.

Третий вопрос спрашивает: « А что **time taken = 4 45025, это означает 4 секунды и 25 мс?»

Мой третий ответ - это 4 секунды и 45025 микросекунд, то есть 4,045025 секунд, что показывает, что OP изменил задачи, выполняемые двумя функциями, которые он ранее рассчитывал.


0
#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

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


0

Я создал класс для автоматического измерения прошедшего времени. Пожалуйста, проверьте код (c ++ 11) по этой ссылке: https://github.com/sonnt174/Common/blob/master/time_measure.h

Пример использования класса TimeMeasure:

void test_time_measure(std::vector<int> arr) {
  TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
  std::sort(begin(arr), end(arr));
}

Мне нравится ваше печатное заявление с единицами. Что нужно для переноса вашего кода на gcc и clang? ( wandbox.org )
— Говард Хиннант

1
@HowardHinnant: спасибо за обращение, я также обновил код для gcc и clang.
— Сирн Нгуен Чыонг

0

Matlab ароматный!

ticзапускает секундомер для измерения производительности. Функция записывает внутреннее время при выполнении команды tic. Отображение прошедшего времени с помощью tocфункции.

#include <iostream>
#include <ctime>
#include <thread>
using namespace std;

clock_t START_TIMER;

clock_t tic()
{
    return START_TIMER = clock();
}

void toc(clock_t start = START_TIMER)
{
    cout
        << "Elapsed time: "
        << (clock() - start) / (double)CLOCKS_PER_SEC << "s"
        << endl;
}

int main()
{
    tic();
    this_thread::sleep_for(2s);
    toc();

    return 0;
}

-4

Вы можете использовать библиотеку SFML , которая является простой и быстрой мультимедийной библиотекой. Он включает в себя множество полезных и четко определенных классов, таких как Clock, Socket, Sound, Graphics и т. Д. Он очень прост в использовании и настоятельно рекомендуется.

Это пример для этого вопроса.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.