2010-11-22 16 views
6

He estado usando hasta ahora, la forma tradicional de los métodos simultáneos de referencia, que es medir la duración transcurrida para un número de carreras:evaluación comparativa utilizando <ctime> e instrucción reordenación

template <typename Functor> 
double benchmark(Functor const& f, size_t nbRuns) 
{ 
    if (nbRuns == 0) { return 0.0; } 

    f(); // Initialize before measuring, I am not interesting in setup cost 

    time_t begin = time(0); 
    for (size_t i = 0; i != nbRuns; ++i) { f(); } 
    time_t end = time(0); 

    return difftime(end, begin); 
} 

que parecía todo bien y elegante hasta que me encontré con esta pregunta: Optimizing away a "while(1);" loop in C++0x.

Lo que me parece raro es que se permite que el compilador para ejecutar la salida antes del bucle ... y de repente me pregunto:

¿Qué impide que el compilador de ejecución de time_t end = time(0); antes del bucle aquí?

porque si lo hiciera, eso de alguna manera atornillaría mi pequeño código de referencia.

Y mientras estamos en ello, si alguna vez el reordenamiento podría ocurrir en esta situación:

¿Cómo se puede evitar que?

no podía pensar en etiquetas relevantes aparte del C++ queridos, si alguien piensa que he perdido uno, no dude en añadir que

+0

¿Cuál es su compilador? ¿Está seguro de que el ciclo sigue ejecutándose después de la salida? Debe insertar printf dentro del ciclo y probarlo. ¿Crea f() otro hilo? Lo que puede ejecutarse después de la salida son otros hilos. – Squall

+0

@Squall: no sucede, o al menos no creo que lo haga, pero me preguntaba si funcionaría por mera casualidad. –

Respuesta

6

Esta es una pregunta difícil.

Lo que impide que el compilador ejecute time_t end = time (0); antes de el ciclo aquí?

En general, nada; de hecho, incluso en C++ 03. Debido a la regla de si-si, el compilador puede emitir cualquier código que tenga el mismo comportamiento observable. Eso significa que, si omite f() no cambia ninguna entrada/salida especificada, o acceso volátil, no puede ejecutar f() en absoluto.

Lo que me sorprende como inusual es que se permite que el compilador para ejecutar la salida antes del bucle

Eso no es realmente cierto - el tema con el bucle vacío es que C++ 0x doesn no cuenta la mera no determinación como comportamiento observable.No es que pueda reordenar el bucle vacío y la salida de "Hello", sino que el compilador puede omitir completamente el bucle vacío.

+0

efectivamente, 'f' es puro cálculo y no uso el resultado, que es lo que me hizo pensar. Llama a funciones no en línea y no creo que LTO pueda detectar su propia (no) pureza, lo que probablemente impida la optimización aquí (supongo ...) –

+0

@Matthieu M .: Sí, es probable que funcione. Sin embargo, el estándar no requiere tal comportamiento (sería bastante difícil de especificar). Los compiladores no están tan ansiosos por rechazar las llamadas a funciones no en línea, pero eso podría cambiar fácilmente en el futuro. – jpalecek

2

Normalmente me pondría mi temporizador en un alcance utilizando una objeto por lo que calcula el "final" en su destructor cuando se sale del alcance.

se permitiría el compilador para ejecutar su destructor, mientras que todavía en el alcance? No lo sé.

Por supuesto time_t sólo mide segundos así que normalmente medir un grano más fino, por lo general milisegundos. A veces, los milisegundos no son lo suficientemente detallados (por ejemplo, funciones muy pequeñas que se llaman muchas veces) en cuyo caso probablemente usaría microsegundos.

Por supuesto, en este caso hay una sobrecarga al entrar y salir del alcance mismo, pero a menudo es una buena medida en un perfil "intrusivo" que a menudo es muy bueno para la optimización en casos reales. (A menudo puede activar y desactivar la función).

Cuestiones relacionadas