Cómo calcular una diferencia horaria en C ++

95

¿Cuál es la mejor manera de calcular una diferencia de tiempo en C ++? Estoy cronometrando la velocidad de ejecución de un programa, así que estoy interesado en milisegundos. Mejor aún, segundos milisegundos ...

La respuesta aceptada funciona, pero debe incluir ctime o time.h como se indica en los comentarios.

Jack BeNimble
fuente
Imitado, pero no puedo vincularlo ahora mismo
Robert Gould
2
La votación para cerrar fue demasiado pequeña, demasiado tarde. Obtuve una respuesta funcional. Buen intento. Por cierto, tampoco pude encontrar un enlace.
Jack BeNimble
¿Es para ventanas? luego intente GetTickCount (API de Windows)
aJ.
5
Robert: Afortunadamente, porque la nueva publicación permitió varias respuestas más, una de las cuales seleccioné. En serio, cuestiono el valor de cerrar una publicación doble. ¿Qué pasa si algunas soluciones no se mencionaron en la primera? ¿Nuevas tecnologías desarrolladas? ¿No puede encontrarlo debido a diferentes títulos?
Jack BeNimble
2
@JackBeNimble ha estado en el extremo receptor de algunos "dups" que no eran exactamente dups (tal vez personas que quizás leyeron rápidamente la pregunta y la marcaron porque suena similar a otra pregunta), estoy totalmente de acuerdo con su punto ... probablemente un punto para el intercambio de
metastack

Respuestas:

123

Ver std::clock()función.

const clock_t begin_time = clock();
// do something
std::cout << float( clock () - begin_time ) /  CLOCKS_PER_SEC;

Si desea calcular el tiempo de ejecución para sí mismo (no para el usuario), es mejor hacerlo en tics de reloj (no en segundos).

EDITAR:
archivos de encabezado responsables - <ctime>o<time.h>

Bayda
fuente
4
Tenga en cuenta que aunque clock () devuelve una cantidad de milisegundos, la precisión de clock () puede ser mucho peor que eso. Por ejemplo, en Windows, la precisión de la función clock () es algo así como 40 ms.
John Dibling
2
Probé esto en Mac 10.7. mi aplicación ejecuta un archivo de 100 mb en 15 segundos, pero el tiempo de diferencia es de 61 segundos. No sirve de mucho. Creo que el tiempo () probablemente sea mejor.
Miek
5
clock()devuelve el tiempo de CPU consumido por el programa. Entonces, si el programa se ejecuta en paralelo, el tiempo devuelto por la función sería el acumulado del tiempo empleado en todas las CPU, en lugar del tiempo transcurrido cplusplus.com/reference/ctime/clock
Ameer Jewdaki
3
Esta respuesta es engañosa porque muestra el tiempo de la CPU, no el tiempo real del reloj de pared.
Ultravioleta
1
Tengo que estar de acuerdo con Ultraviolet aquí, usar el tiempo de la CPU para medir la velocidad de un programa parece incorrecto. OP debería desmarcar esto como la respuesta correcta. En mi opinión, debe usar std :: chrono :: stable_clock :: now () como se describe en varias respuestas en el siguiente hilo stackoverflow.com/questions/2808398/easily-measure-elapsed-time
arunsun
37

si está usando c ++ 11, aquí hay un contenedor simple (vea esta esencia ):

#include <iostream>
#include <chrono>

class Timer
{
public:
    Timer() : beg_(clock_::now()) {}
    void reset() { beg_ = clock_::now(); }
    double elapsed() const { 
        return std::chrono::duration_cast<second_>
            (clock_::now() - beg_).count(); }

private:
    typedef std::chrono::high_resolution_clock clock_;
    typedef std::chrono::duration<double, std::ratio<1> > second_;
    std::chrono::time_point<clock_> beg_;
};

O para c ++ 03 en * nix:

#include <iostream>
#include <ctime>

class Timer
{
public:
    Timer() { clock_gettime(CLOCK_REALTIME, &beg_); }

    double elapsed() {
        clock_gettime(CLOCK_REALTIME, &end_);
        return end_.tv_sec - beg_.tv_sec +
            (end_.tv_nsec - beg_.tv_nsec) / 1000000000.;
    }

    void reset() { clock_gettime(CLOCK_REALTIME, &beg_); }

private:
    timespec beg_, end_;
};

Ejemplo de uso:

int main()
{
    Timer tmr;
    double t = tmr.elapsed();
    std::cout << t << std::endl;

    tmr.reset();
    t = tmr.elapsed();
    std::cout << t << std::endl;
    return 0;
}
gongzhitaao
fuente
2
Otra opción sería usar boost :: chrono en lugar del espacio de nombres C ++ 11 STL std :: chrono. Gracias por tu código
Didac Perez Parera
Cuidado: esto no funcionará si el usuario cambia su tiempo entre Timer()y la llamada a elapsed()if !std::chrono::high_resolution_clock::is_steady, ¡que es el caso en Linux!
jhasse
30

Consideraría seriamente el uso de Boost, particularmente boost :: posix_time :: ptime y boost :: posix_time :: time_duration (en http://www.boost.org/doc/libs/1_38_0/doc/html/date_time/posix_time .html ).

Es multiplataforma, fácil de usar y, en mi experiencia, proporciona el nivel más alto de resolución de tiempo que proporciona un sistema operativo. Posiblemente también muy importante; proporciona algunos operadores de E / S muy agradables.

Para usarlo para calcular la diferencia en la ejecución del programa (a microsegundos; probablemente exagerado), se vería así [escrito en el navegador, no probado]:

ptime time_start(microsec_clock::local_time());
//... execution goes here ...
ptime time_end(microsec_clock::local_time());
time_duration duration(time_end - time_start);
cout << duration << '\n';
Jeremy CD
fuente
3
Pero boost local_time () no es monótono, por lo que no debe usarse para medir lapsos de tiempo. No he encontrado una forma de acceder al tiempo monótono desde Boost.
gatopeich
27

Agregué esta respuesta para aclarar que la respuesta aceptada muestra el tiempo de CPU que puede no ser el tiempo que desea. Porque según la referencia , hay tiempo de CPU y tiempo de reloj de pared . El tiempo del reloj de pared es el tiempo que muestra el tiempo real transcurrido independientemente de cualquier otra condición, como la CPU compartida por otros procesos. Por ejemplo, utilicé varios procesadores para hacer una determinada tarea y el tiempo de la CPU fue de 18 segundos, donde en realidad tomó 2 segundos. en el tiempo real del reloj de pared.

Para obtener el tiempo real que lo hace,

#include <chrono>

auto t_start = std::chrono::high_resolution_clock::now();
// the work...
auto t_end = std::chrono::high_resolution_clock::now();

double elapsed_time_ms = std::chrono::duration<double, std::milli>(t_end-t_start).count();
Ultravioleta
fuente
2
No hubiera podido usar std :: chrono sin esta respuesta, ¡gracias!
giles
13

boost 1.46.0 y versiones posteriores incluyen la biblioteca Chrono :

La clase thread_clock proporciona acceso al reloj de pared de hilo real, es decir, el reloj de tiempo de CPU real del hilo de llamada. La hora actual relativa del hilo se puede obtener llamando a thread_clock :: now ()

#include <boost/chrono/thread_clock.hpp>
{
...
    using namespace boost::chrono;
    thread_clock::time_point start = thread_clock::now();
    ...
    thread_clock::time_point stop = thread_clock::now();  
    std::cout << "duration: " << duration_cast<milliseconds>(stop - start).count() << " ms\n";
Gabi Davar
fuente
7
Además, C ++ 11 tiene un std::chronoespacio de nombres con casi el mismo contenido.
ulidtko
12

En Windows: use GetTickCount

//GetTickCount defintition
#include <windows.h>
int main()
{

    DWORD dw1 = GetTickCount();

    //Do something 

    DWORD dw2 = GetTickCount();

    cout<<"Time difference is "<<(dw2-dw1)<<" milliSeconds"<<endl;

}
aJ.
fuente
8

También puede utilizar clock_gettime . Este método se puede utilizar para medir:

  1. Reloj en tiempo real de todo el sistema
  2. Reloj monotónico de todo el sistema
  3. Por tiempo de CPU de proceso
  4. Por proceso Thread CPU time

El código es el siguiente:

#include < time.h >
#include <iostream>
int main(){
  timespec ts_beg, ts_end;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_beg);
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_end);
  std::cout << (ts_end.tv_sec - ts_beg.tv_sec) + (ts_end.tv_nsec - ts_beg.tv_nsec) / 1e9 << " sec";
}

'

Ricardo
fuente
6

en caso de que esté en Unix, puede usar timepara obtener el tiempo de ejecución:

$ g++ myprog.cpp -o myprog
$ time ./myprog
fengshaun
fuente
5

Solo una nota al margen: si está ejecutando Windows y realmente necesita precisión, puede usar QueryPerformanceCounter . Te da tiempo en (potencialmente) nano segundos.

v3.
fuente
5

Para mí, la forma más sencilla es:

#include <boost/timer.hpp>

boost::timer t;
double duration;

t.restart();
/* DO SOMETHING HERE... */
duration = t.elapsed();

t.restart();
/* DO OTHER STUFF HERE... */
duration = t.elapsed();

usando este fragmento de código no tienes que hacer el clásico end - start.

Disfrute de su enfoque favorito.

usuario1823890
fuente
¿t.elapsed () en seg o mili-seg?
mkuse
4

Obtenga el tiempo del sistema en milisegundos al principio, y nuevamente al final, y reste.

Para obtener el número de milisegundos desde 1970 en POSIX, escribiría:

struct timeval tv;

gettimeofday(&tv, NULL);
return ((((unsigned long long)tv.tv_sec) * 1000) +
        (((unsigned long long)tv.tv_usec) / 1000));

Para obtener la cantidad de milisegundos desde 1601 en Windows, escribiría:

SYSTEMTIME systime;
FILETIME filetime;

GetSystemTime(&systime);
if (!SystemTimeToFileTime(&systime, &filetime))
    return 0;

unsigned long long ns_since_1601;
ULARGE_INTEGER* ptr = (ULARGE_INTEGER*)&ns_since_1601;

// copy the result into the ULARGE_INTEGER; this is actually
// copying the result into the ns_since_1601 unsigned long long.
ptr->u.LowPart = filetime.dwLowDateTime;
ptr->u.HighPart = filetime.dwHighDateTime;

// Compute the number of milliseconds since 1601; we have to
// divide by 10,000, since the current value is the number of 100ns
// intervals since 1601, not ms.
return (ns_since_1601 / 10000);

Si quisiera normalizar la respuesta de Windows para que también devolviera el número de milisegundos desde 1970, entonces tendría que ajustar su respuesta en 11644473600000 milisegundos. Pero eso no es necesario si lo único que le importa es el tiempo transcurrido.

Jared Oberhaus
fuente
4

Si está usando:

tstart = clock();

// ...do something...

tend = clock();

Entonces necesitará lo siguiente para obtener el tiempo en segundos:

time = (tend - tstart) / (double) CLOCKS_PER_SEC;
Robert White
fuente
0

Esto parece funcionar bien para intel Mac 10.7:

#include <time.h>

time_t start = time(NULL);


    //Do your work


time_t end = time(NULL);
std::cout<<"Execution Time: "<< (double)(end-start)<<" Seconds"<<std::endl;
Miek
fuente