2008-10-06 8 views
16

Estoy tratando de encontrar la forma de obtener el tiempo de ejecución de una sección de código en C. Ya he intentado tanto time() como clock() desde time.h, pero parece que time() devuelve segundos y clock() parece darme milisegundos (¿o centisegundos?). Sin embargo, me gustaría algo más preciso. ¿Hay alguna manera de tomar el tiempo con una precisión de al menos microsegundos?¿Cómo puedo encontrar el tiempo de ejecución de una sección de mi programa en C?

Esto solo necesita compilar en Linux.

Respuesta

15

Usted se refirió a clock() y time() - estaba buscando gettimeofday()? Eso completará un struct timeval, que contiene segundos y microsegundos.

Por supuesto, la resolución real corresponde al hardware.

1

Es posible que desee buscar en Google instrumentación herramienta.

11

Quiere una aplicación profiler.

palabras clave de búsqueda en los motores de búsqueda y SO: Linux perfilado

+2

Un Profiler proporciona información estadística, que no es lo mismo que una medición real. –

2

Prueba "bench.h"; te permite poner un START_TIMER; y STOP_TIMER ("nombre"); en su código, lo que le permite comparar de forma arbitraria cualquier sección de código (nota: solo se recomienda para secciones cortas, no para cosas que tarden docenas de milisegundos o más). Es preciso para el ciclo del reloj, aunque en algunos casos raros puede cambiar la forma en que se compila el código intermedio, en cuyo caso es mejor utilizar un generador de perfiles (aunque los perfiles generalmente requieren más esfuerzo para secciones específicas del código).

Solo funciona en x86.

+0

Bueno, tenemos uno similar, con una adición útil, PERF_MARK. Esto permitirá marcar el punto de multiplicar almacenado en una matriz estática. Tenemos una versión que puede guardar una cadena para facilitar la lectura de los resultados, la matriz contiene 100 entradas por defecto, pero puede modificarse. PERF_STOP volcar los resultados. – Ilya

+0

Para quien haya agregado la nota sobre este fallo en sistemas multi-core: Lo eliminé porque simplemente es incorrecto. La macro maneja automáticamente los cambios de contexto y otros cambios repentinos en los valores de RDTSC, por lo que no existe tal problema. Lo uso exclusivamente en máquinas multi-core y funciona bien. –

+0

Dark Shikari: Esto no puede ser correcto, esta macro no puede manejar cosas como conmutadores de contexto preventivos. Simplemente no puedo. Producirá resultados, pero no serán precisos. Además, el tiempo que regresa está calibrado para un procesador Core2 (debido a #define NOP_CYCLES) y tendría que cambiarse para adaptarse. – QAZ

1

No encontrará una llamada a la biblioteca que le permita superar la resolución del reloj de su plataforma. Use un generador de perfiles (man gprof) como otro cartel sugerido, o bien - & sucio - ponga un círculo alrededor de la sección ofensiva del código para ejecutarlo muchas veces, y use clock().

0

Si está desarrollando en x86 o x64, ¿por qué no utiliza el contador de sellos de tiempo: RDTSC.

Será más confiable que las funciones de Ansi C como time() o clock() ya que RDTSC es una función atómica. El uso de funciones C para este propósito puede presentar problemas, ya que no se garantiza que el hilo en el que se ejecutan no se desconecte y, como resultado, el valor que devuelvan no será una descripción precisa del tiempo real de ejecución que se intenta medir. .

Con RDTSC puede medir mejor esto. Deberá convertir la cuenta de ticks en un formato de H: M: S de tiempo legible para el ser humano, que dependerá de la frecuencia de reloj del procesador, pero estará en google y estoy seguro de que encontrará ejemplos.

Sin embargo, incluso con RDTSC, incluirá la hora en que se interrumpió la ejecución del código, mientras que una mejor solución que el uso de tiempo()/reloj() si necesita una medición exacta tendrá que recurrir a un generador de perfiles instrumentará su código y lo tendrá en cuenta cuando su código no se esté ejecutando debido a cambios de contexto o lo que sea.

12

Por si sirve de algo, aquí hay uno que es sólo un par de macros:

#include <time.h> 
clock_t startm, stopm; 
#define START if ((startm = clock()) == -1) {printf("Error calling clock");exit(1);} 
#define STOP if ((stopm = clock()) == -1) {printf("Error calling clock");exit(1);} 
#define PRINTTIME printf("%6.3f seconds used by the processor.", ((double)stopm-startm)/CLOCKS_PER_SEC); 

A continuación, sólo lo uso con:

main() { 
    START; 
    // Do stuff you want to time 
    STOP; 
    PRINTTIME; 
} 

De http://ctips.pbwiki.com/Timer

0

Depende de las condiciones .. Los perfiladores son agradables para las vistas globales generales; sin embargo, si realmente necesita una vista precisa, mi recomendación es KISS. Simplemente ejecute el código en un bucle de tal manera que demore un minuto o más en completarse. Luego calcule un promedio simple basado en el tiempo de ejecución total y las iteraciones ejecutadas.

Este enfoque le permite:

  1. obtener resultados precisos con temporizadores de baja resolución.

  2. No se debe tener en cuenta que la instrumentación interfiere con los cachés de alta velocidad (l2, l1, branch..etc) cerca del procesador. Sin embargo, ejecutar el mismo código en un círculo cerrado también puede proporcionar resultados optimistas que pueden no reflejar las condiciones del mundo real.

0

No sé a qué ambiente/OS que se está trabajando, pero el tiempo puede ser inexacto si otro hilo, una tarea o proceso se adelanta a su código programado en el medio. Sugiero explorar mecanismos como mutexes o semáforos para evitar que otros subprocesos preemsen su proceso.

1

gettimeofday() le proporciona una resolución de microsegundos, mientras que clock_gettime() le proporciona una resolución de nanosegundos.

int clock_gettime(clockid_t clk_id, struct timespec *tp); 

El clk_id identifica el reloj que se utilizará. Use CLOCK_REALTIME si desea que un reloj de todo el sistema sea visible para todos los procesos. Use CLOCK_PROCESS_CPUTIME_ID para el temporizador por proceso y CLOCK_THREAD_CPUTIME_ID para un temporizador específico de la secuencia.

Cuestiones relacionadas