Mida fácilmente el tiempo transcurrido


297

Estoy tratando de usar time () para medir varios puntos de mi programa.

Lo que no entiendo es por qué los valores en el antes y el después son los mismos. Entiendo que esta no es la mejor manera de perfilar mi programa, solo quiero ver cuánto tiempo toma algo.

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

doSomthing();
doSomthingLong();

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

Yo he tratado:

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

¿Cómo leo un resultado de **time taken = 0 26339? ¿Eso significa 26,339 nanosegundos = 26.3 ms?

¿Qué pasa **time taken = 4 45025, eso significa 4 segundos y 25 ms?


10
No entiendo la pregunta. Por supuesto, los valores son diferentes. El tiempo pasó en el medio, por lo que time()devuelve un valor diferente.
Thomas

1
¿Qué quiere decir con "No entiendo por qué los valores en el antes y el después son diferentes"? Está obteniendo la hora actual (en segundos desde el 1 de enero de 1970) usando time(NULL)... la segunda vez que llame será N segundos después de la primera y por lo tanto ... diferente (a menos que sea lo que sea que esté haciendo no lo hace) t tome un segundo para completar ... en cuyo caso, será lo mismo que el primero).
Brian Roach

1
¿Puede decirnos qué imprime y cuánto tarda si lo cronometra con un cronómetro o un reloj de pared (o un calendario)?
Matt Curtis

44
Lo siento, quiero decir que ambos valores son MISMOS. Escribí mal mi pregunta.
hap497

Respuestas:


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
sí, esta debería ser la respuesta
Ferenc Dajka

23
Para ejecutar este hay que añadir la #include <chrono>directiva y que cambiaría la hora de presentación como: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(y no se olvide la bandera de C ++ 11 al compilar: -std=c++11)
Antonello

1
Por cierto, esto mide el tiempo de CPU, no el tiempo del reloj de pared. ¿Correcto?
Nikos

44
@ RestlessC0bra Según los documentos de cppreference, "Este reloj no está relacionado con la hora del reloj de pared (por ejemplo, puede ser la hora desde el último reinicio) y es más adecuado para medir intervalos".
cylus

1
¿Qué tipo de datos es este? Std :: chrono :: Duration_cast <std :: chrono :: microsegundos> (end - begin) .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;
}

La time()función solo es precisa en un segundo, pero hay CLOCKS_PER_SEC"relojes" en un segundo. Esta es una medición fácil y portátil, aunque está demasiado simplificada.


129129
Tenga en cuenta que clock()mide el tiempo de CPU, no el tiempo real transcurrido (que puede ser mucho mayor).
jlstrecker

12
Al programar código paralelo para clústeres, este método no refleja el tiempo del mundo real ...
Nicholas Hamilton

3
Esta parece la más fácil de las formas. ¿Le gustaría actualizar o abordar el comentario realizado en @jlstrecker?
Lorah Attkins

55
La solución publicada anteriormente no es una buena solución por muchas razones. Esta es la respuesta correcta - stackoverflow.com/questions/2962785/…
Xofo

1
Probé esta solución y, como lo sugieren los comentarios, mi temporizador funcionó mucho más rápido que el tiempo real.
RTbecard el

267

Puede abstraer el mecanismo de medición del tiempo y hacer que se mida el tiempo de ejecución de cada llamada con un código adicional mínimo , simplemente mediante una llamada a través de una estructura de temporizador. Además, en tiempo de compilación puede parametrizar el tipo de temporización (milisegundos, nanosegundos, etc.).

Gracias a la revisión de Loki Astari y la sugerencia de usar plantillas variadas. Es por eso que la función reenviada se llama.

#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

Según el comentario de Howard Hinnant , es mejor no escapar del sistema cronológico hasta que tengamos que hacerlo. Entonces, la clase anterior podría darle al usuario la opción de llamar countmanualmente al proporcionar un método estático adicional (que se muestra en 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;

y sea más útil para clientes que

"desea procesar un montón de duraciones antes de la E / S (por ejemplo, promedio)"


El código completo se puede encontrar aquí . Aquí se registra mi intento de construir una herramienta de evaluación comparativa basada en crono .


Si C ++ 17 std::invokeestá disponible, la invocación del invocable executionpodría hacerse así:

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

para proporcionar llamadas que son punteros a las funciones de los miembros.


2
Agradable; Tengo algo similar en mi código, pero uso una interfaz diferente a la clase: tengo una clase ( code_timer) que toma el tiempo de inicio ( std::chrono::system_clock::now();) en el constructor, un método code_timer::ellapsedque mide la diferencia entre una nueva now()llamada y la del constructor y un code_timer::resetmétodo que restablece la hora de inicio a un nuevo now()resultado. Para medir la ejecución de un functor en mi código, uso una función libre, fuera de la clase. Esto permite medir el tiempo desde la construcción de un objeto hasta el final de una llamada asíncrona.
utnapistim

77
<nitpick>: no escape del chronosistema hasta que tenga que hacerlo (evite el uso de .count()). Deje que el cliente llame .count()cuando se vea obligado a hacerlo (por ejemplo, para E / S, lo cual es lamentable). El cliente puede querer procesar un montón de duraciones antes de E / S (por ejemplo, promedio) y eso se hace mejor dentro del chronosistema.
Howard Hinnant

1
@ user3241228 1. VS2013 no admite tipos de retorno automático (solo tipos de retorno al final; es una característica de c ++ 14 que aún no está disponible). 2. Creo que esta es la razón, pero le pregunté a aq solo para estar seguro
Nikos Athanasiou

2
¿Por qué no std::forward<F>(func)?
oliora

3
@oliora Es lo mismo. Prefiero std::forward<decltype(func)>(func)porque se puede aplicar a argumentos de lambdas genéricos ( auto&& func) donde Fno está sintácticamente allí y es fácil de abstraer en una macro de utilidad #define fw(arg) std::forward<decltype(arg)>(arg)que hago en mi biblioteca de referencia (por lo que es una sintaxis sobrante en la que no elaboro mucho en la respuesta)
Nikos Athanasiou

56

Como puedo ver en su pregunta, parece que quiere saber el tiempo transcurrido después de la ejecución de algún código. Supongo que sería cómodo ver los resultados en segundos. Si es así, intente usar la difftime()función como se muestra a continuación. Espero que esto resuelva tu problema.

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

44
Esto siempre me da segundos enteros. ¿Se supone que eso suceda?
nitrato de sodio

10
el tiempo siempre solo devolverá segundos, por lo que no se puede usar para mediciones por segundo.
DeepDeadpool

31

Solo Windows: (La etiqueta de Linux se agregó después de publicar esta respuesta)

Puede usar GetTickCount () para obtener la cantidad de milisegundos que han transcurrido desde que se inició el sistema.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

77
Lo estoy usando en Linux. Entonces no puedo usar la función GetTickCount ().
hap497

1
ya no importa;) Gracias por actualizar la etiqueta de tu publicación
RvdK

Funciona y proporciona el tiempo real, no el tiempo de CPU. Lo probé colocando SleepEx(5000,0)en lugar de // Realice una operación que consume mucho tiempo y la diferencia de aftery beforefue casi 5 segundos.
Ruchir

14

time(NULL)devuelve el número de segundos transcurridos desde el 01/01/1970 a las 00:00 ( la Época ). Entonces, la diferencia entre los dos valores es la cantidad de segundos que tomó su procesamiento.

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

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

Puede obtener resultados más precisos getttimeofday(), que devuelven el tiempo actual en segundos, como lo time()hace y también en microsegundos.


13

la función de tiempo (NULL) devolverá el número de segundos transcurridos desde el 01/01/1970 a las 00:00. Y debido a que esa función se llama en un momento diferente en su programa, siempre será un tiempo diferente en C ++


No sé por qué alguien votó en contra, pero su respuesta no es del todo correcta. Para empezar, no devuelve la fecha y hora, y no siempre será diferente.
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)

El uso está debajo ::

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

Esto es similar a RAII en alcance

NOTA: esto no es mío, pero pensé que era relevante aquí


1
incluye desaparecidos
Stepan Yakovenko

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
Si bien se agradece su respuesta, preferimos un preámbulo que contenga una breve descripción del código. Gracias.
Kev

2
Este no es el tiempo transcurrido, sino el tiempo del procesador.
JonnyJD

8

Los valores impresos por su segundo programa son segundos y microsegundos.

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 tiene una clara ventaja de ser multiplataforma. Sin embargo, también introduce una sobrecarga significativa en comparación con POSIX clock_gettime (). En mi caja de Linux todostd::chrono::xxx_clock::now() sabores funcionan más o menos igual:

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

¡Aunque POSIX clock_gettime(CLOCK_MONOTONIC, &time)debería ser igual steady_clock::now()pero es más de x3 veces más rápido!

Aquí está mi prueba, para completar.

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

Y esta es la salida que obtengo cuando se compila con 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

La time(NULL)llamada de función devolverá el número de segundos transcurridos desde epoc: 1 de enero de 1970. Quizás lo que quiera hacer es tomar la diferencia entre dos marcas de tiempo:

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

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

3

Como otros ya han señalado, la función time () en la biblioteca estándar de C no tiene una resolución mejor que un segundo. La única función C totalmente portátil que puede proporcionar una mejor resolución parece ser clock (), pero mide el tiempo del procesador en lugar del tiempo del reloj de pared. Si uno se contenta con limitarse a las plataformas POSIX (por ejemplo, Linux), entonces la función clock_gettime () es una buena opción.

Desde C ++ 11, hay muchas mejores instalaciones de temporización disponibles que ofrecen una mejor resolución en una forma que debería ser muy portátil en diferentes compiladores y sistemas operativos. Del mismo modo, la biblioteca boost :: datetime proporciona buenas clases de temporización de alta resolución que deberían ser altamente portátiles.

Un desafío en el uso de cualquiera de estas instalaciones es el retraso de tiempo introducido al consultar el reloj del sistema. Al experimentar con clock_gettime (), boost :: datetime y std :: chrono, este retraso puede ser fácilmente una cuestión de microsegundos. Por lo tanto, al medir la duración de cualquier parte de su código, debe permitir que haya un error de medición de alrededor de este tamaño, o tratar de corregir ese error cero de alguna manera. Idealmente, es posible que desee recopilar múltiples mediciones del tiempo que le toma a su función y calcular el tiempo promedio o máximo / mínimo en muchas ejecuciones.

Para ayudar con todos estos problemas de portabilidad y recopilación de estadísticas, he estado desarrollando la biblioteca cxx-rtimers disponible en Github que trata de proporcionar una API simple para sincronizar bloques de código C ++, calcular cero errores e informar estadísticas de múltiples temporizadores integrados en tu código Si tiene un compilador de C ++ 11, simplemente #include <rtimers/cxx11.hpp>, y use algo como:

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

Al salir del programa, obtendrá un resumen de las estadísticas de sincronización escritas en std :: cerr como:

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

que muestra el tiempo medio, su desviación estándar, los límites superior e inferior, y la cantidad de veces que se llamó a esta función.

Si desea utilizar funciones de temporización específicas de Linux, puede hacerlo #include <rtimers/posix.hpp>, o si tiene las bibliotecas Boost pero un compilador C ++ anterior, puede hacerlo #include <rtimers/boost.hpp>. También hay versiones de estas clases de temporizador que pueden recopilar información estadística de temporización de varios subprocesos. También hay métodos que le permiten estimar el error cero asociado con dos consultas inmediatamente consecutivas del reloj del sistema.


2

Internamente, la función accederá al reloj del sistema, por lo que devuelve diferentes valores cada vez que lo llama. En general, con lenguajes no funcionales puede haber muchos efectos secundarios y estados ocultos en funciones que no se pueden ver simplemente mirando el nombre y los argumentos de la función.


2

De lo que se ve, tv_sec almacena los segundos transcurridos, mientras que tv_usec almacena los microsegundos transcurridos por separado. Y no son las conversiones de cada uno. Por lo tanto, deben cambiarse a la unidad adecuada y agregarse para obtener el tiempo total transcurrido.

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

En Linux, clock_gettime () es una de las buenas opciones. Debe vincular la biblioteca en tiempo real (-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

Necesitaba medir el tiempo de ejecución de funciones individuales dentro de una biblioteca. No quería tener que ajustar cada llamada de cada función con una función de medición de tiempo porque es fea y profundiza la pila de llamadas. Tampoco quería poner el código del temporizador en la parte superior e inferior de cada función porque hace un desastre cuando la función puede salir temprano o lanzar excepciones, por ejemplo. Entonces, lo que terminé haciendo fue hacer un temporizador que usa su propia vida útil para medir el tiempo.

De esta manera, puedo medir el tiempo de pared que tomó un bloque de código simplemente instanciando uno de estos objetos al comienzo del bloque de código en cuestión (función o cualquier alcance realmente) y luego permitiendo que el destructor de instancias mida el tiempo transcurrido desde construcción cuando la instancia queda fuera de alcance. Puede encontrar el ejemplo completo aquí, pero la estructura es extremadamente simple:

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); }
};

La estructura le devolverá la llamada al functor proporcionado cuando esté fuera de alcance para que pueda hacer algo con la información de tiempo (imprimirla o almacenarla o lo que sea). Si necesita hacer algo aún más complejo incluso se podría utilizar std::bindcon std::placeholdersregresar la llamada funciones con más argumentos.

Aquí hay un ejemplo rápido de su uso:

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));
}

Si desea ser más deliberado, también puede usar newy deletepara iniciar y detener explícitamente el temporizador sin depender del alcance para hacerlo por usted.


1

Son iguales porque su función doSomething ocurre más rápido que la granularidad del temporizador. Tratar:

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

La razón por la que ambos valores son iguales es porque su procedimiento largo no toma tanto tiempo, menos de un segundo. Puede intentar simplemente agregar un bucle largo (para (int i = 0; i <100000000; i ++);) al final de la función para asegurarse de que este sea el problema, entonces podemos ir desde allí ...

En caso de que lo anterior resulte ser cierto, necesitará encontrar una función de sistema diferente (entiendo que trabaja en Linux, así que no puedo ayudarlo con el nombre de la función) para medir el tiempo con mayor precisión. Estoy seguro de que hay una función similar a GetTickCount () en Linux, solo necesita encontrarla.


1

Usualmente uso lo siguiente:

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

Es lo mismo que propuso @ nikos-athanasiou, excepto que evito el uso de un reloj no estable y uso un número flotante de segundos como duración.


1
En este interruptor de tipo : Normalmente high_resolution_clockes un typedef para cualquiera system_clocko steady_clock. Entonces, para rastrear que std::conditionalsi la is_steadyparte es verdadera, entonces elige high_resolution_clockcuál es (un typedef to) the steady_clock. Si es falso, elige el steady_clocknuevo. Sólo tiene que utilizar steady_clockdesde el principio ...
Nikos Athanasiou

@ nikos-athanasiou Estoy completamente de acuerdo con el comentario de 5gon12eder de que el estándar no requiere un caso "típico", por lo que algunos STL pueden implementarse de manera diferente. Prefiero que mi código sea más genérico y no esté relacionado con los detalles de implementación.
oliora

No es necesario, pero indica explícitamente en 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. La razón es esta: high_resolution_clockrepresenta los relojes con el período de tick más corto, por lo que sea cual sea la implementación, tiene dos opciones, ser estable o no. Independientemente de la elección que hagamos, decir que la implementación será diferente de los otros dos relojes es como decir que tenemos una mejor implementación para un reloj estable (o no) que elegimos no usar (para relojes estables o no). Saber cómo es bueno, saber por qué es mejor
Nikos Athanasiou

@ nikos-athanasiou Preferiría ser 100% seguro, especialmente cuando esto no me costó sobrecarga de tiempo de ejecución y sobrecarga de tiempo de compilación indetectable. Puede confiar en "mayo" y asaltos si lo desea.
oliora

au contraire mi amigo, eres tú quien confía en "mayo", pero conviene a ti mismo. Si desea estar 100% seguro y seguir escribiendo esto, también debe encontrar una manera, para usted y los usuarios de su código, de evitar puntos de tiempo de mezcla no portables de diferentes relojes (si alguna vez este tipo de interruptor adquiere un significado, se comportará de manera diferente en diferentes plataformas). ¡Que te diviertas!
Nikos Athanasiou

0

En respuesta a las tres preguntas específicas de OP .

"Lo que no entiendo es por qué los valores en el antes y el después son los mismos ".

La primera pregunta y el código de muestra muestran que time()tiene una resolución de 1 segundo, por lo que la respuesta debe ser que las dos funciones se ejecuten en menos de 1 segundo. Pero ocasionalmente informará (aparentemente ilógicamente) 1 segundo si las dos marcas de temporizador se extienden a horcajadas sobre un límite de un segundo.

El siguiente ejemplo usa gettimeofday()qué llena esta estructura

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

y la segunda pregunta es : "¿Cómo leo un resultado **time taken = 0 26339? ¿Eso significa 26,339 nanosegundos = 26.3 mseg?"

Mi segunda respuesta es que el tiempo necesario es de 0 segundos y 26339 microsegundos, es decir, 0.026339 segundos, lo que confirma el primer ejemplo que se ejecuta en menos de 1 segundo.

La tercera pregunta es : "¿Qué tal **time taken = 4 45025si eso significa 4 segundos y 25 ms?"

Mi tercera respuesta es que el tiempo necesario es de 4 segundos y 45025 microsegundos, es decir, 4.045025 segundos, lo que muestra que OP ha alterado las tareas realizadas por las dos funciones que previamente cronometró.


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

}

Ejemplo similar a uno disponible aquí, solo con función de conversión adicional + imprimir.


0

He creado una clase para medir automáticamente el tiempo transcurrido. Verifique el código (c ++ 11) en este enlace: https://github.com/sonnt174/Common/blob/master/time_measure.h

Ejemplo de cómo usar la clase TimeMeasure:

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

Me gusta su declaración impresa con las unidades. ¿Qué se necesitaría para transferir su código a gcc y clang? ( wandbox.org )
Howard Hinnant

1
@HowardHinnant: gracias por abordar, también actualicé el código para gcc y clang.
Sirn Nguyen Truong

0

Matlab ¡sazonado!

ticinicia un cronómetro para medir el rendimiento. La función registra el tiempo interno en la ejecución del comando tic. Muestra el tiempo transcurrido con la tocfunción.

#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

Puede usar la biblioteca SFML , que es una biblioteca multimedia simple y rápida. Incluye muchas clases útiles y bien definidas como Reloj, Socket, Sonido, Gráficos, etc. Es muy fácil de usar y muy recomendable.

Este es un ejemplo para esta pregunta.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.