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?
time()
devuelve un valor diferente.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).Respuestas:
fuente
#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
)La
time()
función solo es precisa en un segundo, pero hayCLOCKS_PER_SEC
"relojes" en un segundo. Esta es una medición fácil y portátil, aunque está demasiado simplificada.fuente
clock()
mide el tiempo de CPU, no el tiempo real transcurrido (que puede ser mucho mayor).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.
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
count
manualmente al proporcionar un método estático adicional (que se muestra en C ++ 14)y sea más útil para clientes que
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::invoke
está disponible, la invocación del invocableexecution
podría hacerse así:para proporcionar llamadas que son punteros a las funciones de los miembros.
fuente
code_timer
) que toma el tiempo de inicio (std::chrono::system_clock::now();
) en el constructor, un métodocode_timer::ellapsed
que mide la diferencia entre una nuevanow()
llamada y la del constructor y uncode_timer::reset
método que restablece la hora de inicio a un nuevonow()
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.chrono
sistema 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 delchrono
sistema.std::forward<F>(func)
?std::forward<decltype(func)>(func)
porque se puede aplicar a argumentos de lambdas genéricos (auto&& func
) dondeF
no 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)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.fuente
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.
fuente
SleepEx(5000,0)
en lugar de // Realice una operación que consume mucho tiempo y la diferencia deafter
ybefore
fue casi 5 segundos.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.Puede obtener resultados más precisos
getttimeofday()
, que devuelven el tiempo actual en segundos, como lotime()
hace y también en microsegundos.fuente
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 ++
fuente
El uso está debajo ::
Esto es similar a RAII en alcance
NOTA: esto no es mío, pero pensé que era relevante aquí
fuente
fuente
Los valores impresos por su segundo programa son segundos y microsegundos.
fuente
fuente
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 todo
std::chrono::xxx_clock::now()
sabores funcionan más o menos igual:¡Aunque POSIX
clock_gettime(CLOCK_MONOTONIC, &time)
debería ser igualsteady_clock::now()
pero es más de x3 veces más rápido!Aquí está mi prueba, para completar.
Y esta es la salida que obtengo cuando se compila con gcc7.2 -O3:
fuente
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:fuente
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:Al salir del programa, obtendrá un resumen de las estadísticas de sincronización escritas en std :: cerr como:
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.fuente
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.
fuente
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.
fuente
En Linux, clock_gettime () es una de las buenas opciones. Debe vincular la biblioteca en tiempo real (-lrt).
fuente
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:
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::bind
constd::placeholders
regresar la llamada funciones con más argumentos.Aquí hay un ejemplo rápido de su uso:
Si desea ser más deliberado, también puede usar
new
ydelete
para iniciar y detener explícitamente el temporizador sin depender del alcance para hacerlo por usted.fuente
Son iguales porque su función doSomething ocurre más rápido que la granularidad del temporizador. Tratar:
fuente
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.
fuente
Usualmente uso lo siguiente:
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.
fuente
high_resolution_clock
es un typedef para cualquierasystem_clock
osteady_clock
. Entonces, para rastrear questd::conditional
si lais_steady
parte es verdadera, entonces eligehigh_resolution_clock
cuál es (un typedef to) thesteady_clock
. Si es falso, elige elsteady_clock
nuevo. Sólo tiene que utilizarsteady_clock
desde el principio ...high_resolution_clock may be a synonym for system_clock or steady_clock
. La razón es esta:high_resolution_clock
representa 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 mejorEn 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 estructuray 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 45025
si 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ó.
fuente
Ejemplo similar a uno disponible aquí, solo con función de conversión adicional + imprimir.
fuente
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:
fuente
Matlab
¡sazonado!tic
inicia 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 latoc
función.fuente
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.
fuente