Легко вимірюйте минулий час


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 секунд після першого, і таким чином ... інший (якщо тільки все, що ви робите, не робить " t узяти секунду для завершення ... у такому випадку це буде те саме, що і перше).
Брайан Роуч

1
Чи можете ви сказати нам, що він друкує, і скільки часу це займе, якщо ви приділите його секундоміром або настінним годинником (або календарем)?
Метт Кертіс

4
Вибачте, я маю на увазі, що обидва значення однакові. Я неправильно набираю своє запитання.
hap497

Відповіді:


335
//***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
так, це повинна бути відповідь
Ferenc Dajka

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, "Цей годинник не пов'язаний з часом настінного годинника (наприклад, це може бути час після останньої перезавантаження), і найбільш підходить для вимірювання інтервалів".
cylus

1
Що таке тип даних? Std :: chrono :: duration_cast <std :: chrono :: мікросекунди> (кінець - початок) .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

Ти можеш абстрагувати механізм вимірювання часу та встановити час роботи кожного виклику, виміряне мінімальним додатковим кодом , просто зателефонувавши через структуру таймера. Крім того, під час компіляції ви можете параметризувати тип часу (мілісекунди, наносекунди тощо).

Завдяки огляду Локі Астарі та пропозиції використовувати різні шаблони. Ось чому переадресований виклик функції.

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

і бути найбільш корисним для клієнтів, які

"хочу обробити купу тривалості до вводу / виводу (наприклад, середній)"


Повний код можна знайти тут . Записана моя спроба побудувати інструмент бенчмаркінгу на основі хроно тут .


Якщо C ++ 17-х std::invoke доступно , виклик дзвінка, який executionможна викликати, може бути виконаний так:

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

передбачити дзвінки, що є покажчиками на функції членів.


2
Ніцца; У моєму коді є щось подібне, але я використовую інший інтерфейс до класу: у мене є клас ( 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)тому що він може застосовуватися до аргументів загальних лямбдашів ( 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
вже не маю уваги;) Дякую за оновлення тегу вашого допису
RvdK

Він працює і дає реальний час, а не час процесора. Я перевірив це, помістивши SleepEx(5000,0)на місце // Виконання трудомісткої операції та різниці afterі beforeсклав майже 5 сек.
Рухір

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. А тому, що ця функція викликається в різний час у вашій програмі, вона завжди буде різною Time в C ++


Я не знаю, чому хтось прихильнився, але ваша відповідь не зовсім правильна. Для початківців він не повертає час дати і не завжди буде різним.
Метт Столяр

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()але він у більш ніж x3 рази швидший!

Ось мій тест, на повноту.

#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, яка може забезпечити кращу роздільну здатність, є годинник (), але він вимірює час процесора, а не час настінного годинника. Якщо ви вмієте обмежувати себе платформами 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 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 to) 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% безпечним, особливо якщо це не коштувало мені накладних витрат та невизначеного накладного часу компіляції. Ви можете розраховувати на "може" та припущення, якщо хочете.
oliora

au contraire, мій друг, саме ти покладається на "може", але влаштовуєш себе. Якщо ви хочете бути на 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 секунди, що свідчить про те, що ОП змінив завдання, виконані двома функціями, які він раніше приурочував.


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.