Tengo un programa en C que pretende ejecutarse en paralelo en varios procesadores. Necesito poder registrar el tiempo de ejecución (que puede ser de 1 segundo a varios minutos). He buscado respuestas, pero todas parecen sugerir el uso de la clock()
función, que luego implica calcular el número de relojes que tomó el programa dividido por el Clocks_per_second
valor.
¿No estoy seguro de cómo Clocks_per_second
se calcula el valor?
En Java, solo tomo el tiempo actual en milisegundos antes y después de la ejecución.
¿Hay algo similar en C? He echado un vistazo, pero parece que no puedo encontrar una manera de obtener algo mejor que una segunda resolución.
También sé que un perfilador sería una opción, pero estoy buscando implementar un temporizador yo mismo.
Gracias
fuente
Respuestas:
CLOCKS_PER_SEC
es una constante que se declara en<time.h>
. Para obtener el tiempo de CPU utilizado por una tarea dentro de una aplicación C, use:Tenga en cuenta que esto devuelve el tiempo como un tipo de punto flotante. Esto puede ser más preciso que un segundo (por ejemplo, mide 4.52 segundos). La precisión depende de la arquitectura; en sistemas modernos, obtiene fácilmente 10 ms o menos, pero en máquinas Windows más antiguas (de la era Win98) estaba más cerca de 60 ms.
clock()
es el estándar C; funciona "en todas partes". Hay funciones específicas del sistema, comogetrusage()
en sistemas tipo Unix.Java
System.currentTimeMillis()
no mide lo mismo. Es un "reloj de pared": puede ayudarlo a medir cuánto tiempo le llevó ejecutar el programa, pero no le dice cuánto tiempo de CPU se utilizó. En un sistema multitarea (es decir, todos ellos), estos pueden ser muy diferentes.fuente
clock()
devuelve un tiempo en una escala interna llamada "relojes", yCLOCKS_PER_SEC
es el número de relojes por segundo, por lo que dividir porCLOCKS_PER_SEC
rendimientos un tiempo en segundos. En el código anterior, el valor es adouble
para que pueda escalarlo a voluntad.CLOCKS_PER_SEC
es unlong int
valor1000000
, que da tiempo en microsegundos cuando no está dividido; no ciclos de reloj de la CPU. Por lo tanto, no es necesario tener en cuenta la frecuencia dinámica, ya que el reloj aquí está en microsegundos (¿tal vez ciclos de reloj para una CPU de 1 MHz?) Hice un breve programa en C imprimiendo ese valor y fue 1000000 en mi computadora portátil i7-2640M, con frecuencia dinámica que permite de 800 MHz a 2.8 GHz, incluso usando Turbo Boost para llegar hasta 3.5 GHz.Si está utilizando el shell de Unix para ejecutar, puede usar el comando time.
haciendo
suponiendo a.out como el ejecutable le dará el tiempo necesario para ejecutar esto
fuente
perf stat ./a.out
para obtener contadores de rendimiento de hardware para errores de caché y predicciones erróneas de sucursales, e IPC.En vainilla simple C:
fuente
Funcionalmente quieres esto:
Tenga en cuenta que esto mide en microsegundos, no solo segundos.
fuente
gettimeofday
es obsoleto y no se recomienda para código nuevo. Su página de manual POSIX recomienda clock_gettime en su lugar, lo que le permite pedirCLOCK_MONOTONIC
que no se vea afectado por los cambios en el reloj del sistema y, por lo tanto, es mejor como un intervalo de tiempo. (Ver la respuesta de JohnSll ). En los sistemas Linux modernos, por ejemplo, gettimeofday es básicamente un contenedor para clock_gettime que convierte nanosegundos a microsegundos.La mayoría de los programas simples tienen tiempo de cálculo en milisegundos. Entonces, supongo, esto lo encontrará útil.
Si desea calcular el tiempo de ejecución de todo el programa y está en un sistema Unix, ejecute su programa usando el comando de tiempo como este
time ./a.out
fuente
Se han sugerido muchas respuestas
clock()
y luegoCLOCKS_PER_SEC
detime.h
. Probablemente sea una mala idea, porque esto es lo/bits/time.h
que dice mi archivo:Por
CLOCKS_PER_SEC
lo tanto, podría definirse como 1000000, dependiendo de las opciones que use para compilar, por lo que no parece una buena solución.fuente
CLOCK_PER_SEC==1000000
, pero al mismo tiempo, todos usan precisión de 1 µs para su implementación de reloj (); Por cierto, tiene la buena propiedad para reducir los problemas de intercambio. Si desea medir eventos potencialmente muy rápidos, digamos por debajo de 1 ms, primero debe preocuparse por la precisión (o resolución) de la función clock (), que es necesariamente más gruesa que 1 µs en Posix, pero a menudo también es mucho más gruesa; la solución habitual es ejecutar la prueba muchas veces; Sin embargo, la pregunta formulada no parecía requerirla.clock()
, si divide ese valor conCLOCK_PER_SEC
usted, se garantiza que obtendrá el tiempo en segundos que tomó la CPU. La responsabilidad de medir la velocidad real del reloj es responsabilidad de laclock()
función, no suya.La respuesta de Thomas Pornin como macros:
Úselo así:
Salida:
fuente
Debe tener en cuenta que medir el tiempo que tardó un programa en ejecutarse depende mucho de la carga que tenga la máquina en ese momento específico.
Sabiendo que, la forma de obtener el tiempo actual en C se puede lograr de diferentes maneras, una más fácil es:
Espero eso ayude.
¡Saludos!
fuente
(Faltan todas las respuestas aquí, si su administrador del sistema cambia la hora del sistema, o si su zona horaria tiene diferentes horarios de invierno y verano. Por lo tanto ...)
Sobre el uso de Linux:
clock_gettime(CLOCK_MONOTONIC_RAW, &time_variable);
no se ve afectado si el administrador del sistema cambia la hora, o si vives en un país con un horario de invierno diferente del horario de verano, etc.man clock_gettime
estados:fuente
(end.tv_nsec - begin.tv_nsec) / 1000000000.0
resultaría esto0
siempre?double
disparadores literales INT olong
paradouble
conversión antes de la división. Por supuesto, podría limitarse a un número entero e imprimir latv_sec
parte y luego la parte fraccionaria con cero%ld.%09ld
, pero convertir a doble es fácil y 53 bits de precisión suelen ser suficientes para los tiempos de referencia.timespec_subtract
como lotimeval_subtract
sugerido en el manual de glibc : gnu.org/software/libc/manual/html_node/Elapsed-Time.html )ANSI C solo especifica funciones de tiempo de segunda precisión. Sin embargo, si está ejecutando en un entorno POSIX, puede usar gettimeofday () que proporciona una resolución de microsegundos del tiempo transcurrido desde la época de UNIX.
Como nota al margen, no recomendaría usar clock () ya que está mal implementado en muchos sistemas (¿si no todos?) Y no es preciso, además del hecho de que solo se refiere a cuánto tiempo ha pasado su programa en la CPU y no la duración total del programa, que según su pregunta es lo que supongo que le gustaría medir.
fuente
Todas las soluciones no funcionan en mi sistema.
Puedo empezar a usar
fuente
time_t
valores como un doble. Como lostime_t
valores solo son precisos por segundo, tiene un valor limitado para imprimir el tiempo que tardan los programas de ejecución corta, aunque puede ser útil para los programas que se ejecutan durante largos períodos.clock_t
sdifftime
parece funcionar para mí con la precisión de una centésima de segundo. Esto está en Linux x86. Tampoco puedo obtener la resta destop
ystart
para trabajar.difftime()
clock() / CLOCKS_PER_SEC
, ya que espera segundos.fuente
He encontrado que el reloj habitual (), todos lo recomiendan aquí, por alguna razón se desvía enormemente de una ejecución a otra, incluso para el código estático sin efectos secundarios, como dibujar en la pantalla o leer archivos. Podría ser porque la CPU cambia los modos de consumo de energía, el sistema operativo le da diferentes prioridades, etc.
Por lo tanto, la única forma de obtener el mismo resultado de manera confiable cada vez con clock () es ejecutar el código medido en un bucle varias veces (durante varios minutos), tomando precauciones para evitar que el compilador lo optimice: los compiladores modernos pueden calcular previamente el código sin los efectos secundarios que se ejecutan en un bucle, y moverlo fuera del bucle., por ejemplo, usando una entrada aleatoria para cada iteración.
Después de recolectar suficientes muestras en una matriz, se ordena esa matriz y se toma el elemento central, llamado mediana. La mediana es mejor que la media, ya que arroja desviaciones extremas, como decir que el antivirus ocupa toda la CPU o el sistema operativo haciendo alguna actualización.
Aquí hay una sencilla utilidad para medir el rendimiento de ejecución del código C / C ++, promediando los valores cercanos a la mediana: https://github.com/saniv/gauge
Todavía estoy buscando una forma más robusta y rápida de medir el código. Probablemente se podría intentar ejecutar el código en condiciones controladas en el metal desnudo sin ningún sistema operativo, pero eso dará un resultado poco realista, porque en realidad el sistema operativo se involucra.
x86 tiene estos contadores de rendimiento de hardware, que incluyen el número real de instrucciones ejecutadas, pero son difíciles de acceder sin ayuda del sistema operativo, difíciles de interpretar y tienen sus propios problemas ( http://archive.gamedev.net/archive/reference/articles /article213.html ). Aún así, podrían ser útiles para investigar la naturaleza del cuello de la botella (acceso a datos o cálculos reales sobre esos datos).
fuente
performance
) o muchas decenas de milisegundos. en.wikipedia.org/wiki/Dynamic_frequency_scaling . Y sí, el rendimiento medio suele ser una buena opción; el extremo superior generalmente tiene algunos picos de interferencia.main
que toma un argumento y devuelve un resultado, y no use la optimización del tiempo de enlace. Entonces el compilador no puede alinearlo con la persona que llama. Solo funciona si la función ya incluye algún tipo de bucle; de lo contrario, la sobrecarga de llamadas / ret es demasiado alta.Algunos podrían encontrar útil un tipo diferente de información: me dieron este método de medición del tiempo como parte de un curso universitario sobre programación GPGPU con NVidia CUDA ( descripción del curso ). Combina métodos vistos en publicaciones anteriores, y simplemente lo publico porque los requisitos le dan credibilidad:
Supongo que podría multiplicarse con, por ejemplo,
1.0 / 1000.0
para obtener la unidad de medida que se adapte a sus necesidades.fuente
clock_gettime
cambio, su página de manual POSIX recomienda , lo que le permite pedirCLOCK_MONOTONIC
que no se vea afectado por los cambios en el reloj del sistema, y por lo tanto, es mejor como un temporizador de intervalo. En los sistemas Linux modernos, por ejemplo,gettimeofday
es básicamente un contenedorclock_gettime
que convierte nanosegundos a microsegundos. (Ver la respuesta de JohnSll).timeval_subtract
.Comparación del tiempo de ejecución del ordenamiento de burbujas y el ordenamiento de selección Tengo un programa que compara el tiempo de ejecución del ordenamiento de burbujas y el ordenamiento de selección. Para averiguar el tiempo de ejecución de un bloque de código, calcule el tiempo antes y después del bloque por
Código de ejemplo:
fuente