Cómo calcular el tiempo de ejecución de un fragmento de código en C++

9 minutos de lectura

Como calcular el tiempo de ejecucion de un fragmento de
ahmet alp balcánico

Tengo que calcular el tiempo de ejecución de un fragmento de código C++ en segundos. Debe estar funcionando en máquinas Windows o Unix.

Utilizo el siguiente código para hacer esto. (importar antes)

clock_t startTime = clock();
// some code here
// to compute its execution duration in runtime
cout << double( clock() - startTime ) / (double)CLOCKS_PER_SEC<< " seconds." << endl;

Sin embargo, para entradas pequeñas o declaraciones cortas como a = a + 1, obtengo un resultado de “0 segundos”. Creo que debe ser algo así como 0.0000001 segundos o algo así.

yo recuerdo eso System.nanoTime() en Java funciona bastante bien en este caso. Sin embargo, no puedo obtener la misma funcionalidad exacta de clock() función de C++.

tienes una solución?

  • Tenga en cuenta que cualquier comparación basada en la diferencia de tiempo puede ser inexacta debido al hecho de que es posible que el sistema operativo no ejecute su hilo de principio a fin. Puede interrumpirlo y ejecutar otros subprocesos entrelazados con el suyo, lo que tendrá un impacto significativo en el tiempo real necesario para completar su operación. Puede ejecutar varias veces y promediar los resultados; puede minimizar el número de otros procesos en ejecución. Pero ninguno de estos eliminará por completo el efecto de suspensión del hilo.

    – Mordachai

    7 de diciembre de 2009 a las 17:07

  • Mordachi, ¿por qué querrías eliminarlo? Desea ver cómo se desempeña su función en un entorno del mundo real, no en un reino mágico donde los hilos nunca se interrumpen. Siempre que lo ejecute varias veces y haga un promedio, será muy preciso.

    – Tomás Bonini

    7 de diciembre de 2009 a las 17:37

  • Sí, lo ejecuto varias veces y obtengo un promedio de resultados.

    – ahmet alp balkan

    7 de diciembre de 2009 a las 17:54

  • Andreas, el comentario de Mordachai es relevante si el OP desea comparar el rendimiento de su código con un algoritmo diferente. Por ejemplo, si ejecuta varias pruebas de reloj esta tarde y luego prueba un algoritmo diferente mañana por la mañana, es posible que su comparación no sea confiable, ya que puede estar compartiendo recursos con muchos más procesos por la tarde que por la mañana. O tal vez un conjunto de código hará que el sistema operativo le dé menos tiempo de procesamiento. Hay numerosas razones por las que este tipo de medición del rendimiento no es fiable si quiere realizar una comparación basada en el tiempo.

    – weberc2

    30 de agosto de 2012 a las 13:42

  • @Mordachai Sé que estoy respondiendo a un comentario anterior, pero para cualquiera que tropiece con esto como lo hice yo: para medir el rendimiento de los algoritmos, desea tomar el mínimo de algunas ejecuciones, no el promedio. Este es el que tuvo menos interrupciones por parte del sistema operativo y, por lo tanto, cronometra principalmente su código.

    – Baruc

    20 de agosto de 2014 a las 7:52

1646963288 797 Como calcular el tiempo de ejecucion de un fragmento de
Tomás Bonini

Puedes usar esta función que escribí. Llama GetTimeMs64()y devuelve la cantidad de milisegundos transcurridos desde la época de Unix usando el reloj del sistema, al igual que time(NULL)excepto en milisegundos.

Funciona tanto en Windows como en Linux; es seguro para subprocesos.

Tenga en cuenta que la granularidad es de 15 ms en Windows; en linux depende de la implementación, pero también suele ser de 15 ms.

#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <ctime>
#endif

/* Remove if already defined */
typedef long long int64; typedef unsigned long long uint64;

/* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both
 * windows and linux. */

uint64 GetTimeMs64()
{
#ifdef _WIN32
 /* Windows */
 FILETIME ft;
 LARGE_INTEGER li;

 /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it
  * to a LARGE_INTEGER structure. */
 GetSystemTimeAsFileTime(&ft);
 li.LowPart = ft.dwLowDateTime;
 li.HighPart = ft.dwHighDateTime;

 uint64 ret = li.QuadPart;
 ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */
 ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */

 return ret;
#else
 /* Linux */
 struct timeval tv;

 gettimeofday(&tv, NULL);

 uint64 ret = tv.tv_usec;
 /* Convert from micro seconds (10^-6) to milliseconds (10^-3) */
 ret /= 1000;

 /* Adds the seconds (10^0) after converting them to milliseconds (10^-3) */
 ret += (tv.tv_sec * 1000);

 return ret;
#endif
}

  • Para referencia futura: simplemente lo arrojo a un archivo de encabezado y lo uso. Me alegro de tenerlo.

    – Daniel Handojo

    24 de febrero de 2016 a las 3:29

  • yo creo en el metodo gettimeofday puede dar un resultado no deseado si se cambia el reloj del sistema. Si esto fuera un problema para usted, es posible que desee ver clock_gettime en lugar de.

    – Azmísov

    09/03/2016 a las 19:38

  • ¿Tiene este método para Windows alguna ventaja sobre GetTickCount?

    – Microvirus

    20 de abril de 2016 a las 10:58

  • No compila usando gcc -std=c99

    – Asimilador

    6 de febrero de 2017 a las 23:10

  • @MicroVirus: sí, GetTickCount es el tiempo transcurrido desde que se inició el sistema, mientras que mi función devuelve el tiempo desde la época de UNIX, lo que significa que puede usarlo para fechas y horas. Si solo está interesado en el tiempo transcurrido entre dos eventos, el mío sigue siendo una mejor opción porque es un int64; GetTickCount es un int32 y se desborda cada 50 días, lo que significa que puede obtener resultados extraños si los dos eventos que registró están entre el desbordamiento.

    – Tomás Bonini

    3 mayo 2017 a las 22:59

Como calcular el tiempo de ejecucion de un fragmento de
arhuaco

Tengo otro ejemplo de trabajo que usa microsegundos (UNIX, POSIX, etc.).

    #include <sys/time.h>
    typedef unsigned long long timestamp_t;

    static timestamp_t
    get_timestamp ()
    {
      struct timeval now;
      gettimeofday (&now, NULL);
      return  now.tv_usec + (timestamp_t)now.tv_sec * 1000000;
    }

    ...
    timestamp_t t0 = get_timestamp();
    // Process
    timestamp_t t1 = get_timestamp();

    double secs = (t1 - t0) / 1000000.0L;

Aquí está el archivo donde codificamos esto:

https://github.com/arhuaco/junkcode/blob/master/emqbit-bench/bench.c

  • deberías agregar #include <sys/time.h> al comienzo de tu ejemplo.

    – niekas

    11 de junio de 2015 a las 6:43

Como calcular el tiempo de ejecucion de un fragmento de
gongzhitaao

Aquí hay una solución simple en C ++ 11 que le brinda una resolución satisfactoria.

#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 en *nix, para c++03

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

Aquí está el 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;
}

Desde https://gist.github.com/gongzhitaao/7062087

  • Recibo este error con su solución c ++ 11: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version GLIBCXX_3.4.19 not found (required by ../cpu_2d/g500)

    – usuario9869932

    02/09/2015 a las 20:13


  • @julianromera que plataforma estas usando? ¿instaló la biblioteca libstdc++ y g++?

    – gongzhitaao

    02/09/2015 a las 20:32


  • Es una cuadrícula Slurm de Linux ubuntu 12. Lo acabo de arreglar. Agregué -static-libstdc++ al final del enlazador. Gracias por preguntar @gongzhitaao

    – usuario9869932

    02/09/2015 a las 20:42

1646963289 772 Como calcular el tiempo de ejecucion de un fragmento de
Tomás André

#include <boost/progress.hpp>

using namespace boost;

int main (int argc, const char * argv[])
{
  progress_timer timer;

  // do stuff, preferably in a 100x loop to make it take longer.

  return 0;
}

Cuándo progress_timer sale del alcance, imprimirá el tiempo transcurrido desde su creación.

ACTUALIZAR: Aquí hay una versión que funciona sin Boost (probada en macOS/iOS):

#include <chrono>
#include <string>
#include <iostream>
#include <math.h>
#include <unistd.h>

class NLTimerScoped {
private:
    const std::chrono::steady_clock::time_point start;
    const std::string name;

public:
    NLTimerScoped( const std::string & name ) : name( name ), start( std::chrono::steady_clock::now() ) {
    }


    ~NLTimerScoped() {
        const auto end(std::chrono::steady_clock::now());
        const auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>( end - start ).count();

        std::cout << name << " duration: " << duration_ms << "ms" << std::endl;
    }

};

int main(int argc, const char * argv[]) {

    {
        NLTimerScoped timer( "sin sum" );

        float a = 0.0f;

        for ( int i=0; i < 1000000; i++ ) {
            a += sin( (float) i / 100 );
        }

        std::cout << "sin sum = " << a << std::endl;
    }



    {
        NLTimerScoped timer( "sleep( 4 )" );

        sleep( 4 );
    }



    return 0;
}

Windows proporciona la función QueryPerformanceCounter(), y Unix tiene gettimeofday() Ambas funciones pueden medir al menos 1 microsegundo de diferencia.

  • Pero el uso de windows.h está restringido. La misma fuente compilada debe ejecutarse tanto en Windows como en Unix. ¿Cómo manejar este problema?

    – ahmet alp balkan

    7 de diciembre de 2009 a las 17:02

  • Luego busque alguna biblioteca de contenedores stackoverflow.com/questions/1487695/…

    – Capitán cómico

    7 de diciembre de 2009 a las 17:04

  • la misma fuente compilada parece que desea ejecutar el mismo binario en ambos sistemas, lo que no parece ser el caso. si quisiste decir la misma fuente entonces un #ifdef debe estar bien (y es a juzgar por la respuesta que ha aceptado), y entonces no veo el problema: #ifdef WIN32 #include <windows.h> ... #else ... #endif.

    – solo alguien

    5 de febrero de 2010 a las 14:20

1646963289 84 Como calcular el tiempo de ejecucion de un fragmento de
carlton henderson

En algunos programas que escribí usé RDTS para tal fin. RDTSC no se trata de tiempo sino de número de ciclos desde el inicio del procesador. Debe calibrarlo en su sistema para obtener un resultado en segundos, pero es realmente útil cuando desea evaluar el rendimiento, es incluso mejor usar el número de ciclos directamente sin intentar volver a cambiarlos a segundos.

(el enlace de arriba es a una página de wikipedia en francés, pero tiene ejemplos de código C++, la versión en inglés es aquí)

  • Pero el uso de windows.h está restringido. La misma fuente compilada debe ejecutarse tanto en Windows como en Unix. ¿Cómo manejar este problema?

    – ahmet alp balkan

    7 de diciembre de 2009 a las 17:02

  • Luego busque alguna biblioteca de contenedores stackoverflow.com/questions/1487695/…

    – Capitán cómico

    7 de diciembre de 2009 a las 17:04

  • la misma fuente compilada parece que desea ejecutar el mismo binario en ambos sistemas, lo que no parece ser el caso. si quisiste decir la misma fuente entonces un #ifdef debe estar bien (y es a juzgar por la respuesta que ha aceptado), y entonces no veo el problema: #ifdef WIN32 #include <windows.h> ... #else ... #endif.

    – solo alguien

    5 de febrero de 2010 a las 14:20

1646963289 702 Como calcular el tiempo de ejecucion de un fragmento de
Tomas Matthews

Sugiero usar las funciones de biblioteca estándar para obtener información de tiempo del sistema.

Si desea una resolución más fina, realice más iteraciones de ejecución. En lugar de ejecutar el programa una vez y obtener muestras, ejecútelo 1000 veces o más.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad