2012-05-04 15 views
20

Acabo de escribir este programa corto en C++ para aproximar el número real de tics de reloj por segundo.¿Por qué CLOCKS_PER_SEC no es la cantidad real de relojes por segundo?

#include <iostream> 
#include <time.h> 

using namespace std; 

int main() { 

    for(int i = 0; i < 10 ; i++) { 

     int first_clock = clock(); 
     int first_time = time(NULL); 

     while(time(NULL) <= first_time) {} 

     int second_time = time(NULL); 
     int second_clock = clock(); 

     cout << "Actual clocks per second = " << (second_clock - first_clock)/(second_time - first_time) << "\n"; 

     cout << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << "\n"; 

    } 

    return 0; 

} 

Cuando ejecuto el programa, obtengo una salida que se ve así.

Actual clocks per second = 199139 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 638164 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 610735 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 614835 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 642327 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 562068 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 605767 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 619543 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 650243 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 639128 
CLOCKS_PER_SEC = 1000000 

¿Por qué el número real de marcas de reloj por segundo no coincide con CLOCKS_PER_SEC? Ni siquiera son aproximadamente iguales. ¿Que está pasando aqui?

+3

Tenga en cuenta que puede bucle durante menos de un segundo. Si llama a 'time', y quedan 200ms para el siguiente segundo, entonces dará un bucle de ~ 200ms. Este probablemente no sea el principal problema aquí, de todos modos. – mfontanini

+0

Correcto, me doy cuenta de que esa es la razón por la cual la primera iteración del ciclo devuelve un resultado más pequeño que las iteraciones subsiguientes. Pero mi pregunta es acerca de las iteraciones posteriores. Creo que debería haber dejado eso en claro. –

+0

Ahora todavía obtiene la sobrecarga de su cout en cada iteración posterior. Espere hasta que esté en el comienzo de un segundo antes de comenzar su medición. – David

Respuesta

24

clock devuelve la cantidad de tiempo invertido en su programa. Hay 1,000,000 ticks de reloj por segundo en total *. Parece que su programa consumió el 60% de ellos.

Algo más usó el otro 40%.

* Está bien, hay prácticamente 1.000.000 reloj por segundo. El número real está normalizado, por lo que su programa percibe 1,000,000 de tics.

17

Desde la página del manual de clock(3):

POSIX requiere que CLOCKS_PER_SEC es igual a 1.000.000 independiente de la resolución real.

Su implementación parece seguir a POSIX al menos en ese sentido.

El funcionamiento de su programa de aquí, me sale

Actual clocks per second = 980000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 990000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 1000000 
CLOCKS_PER_SEC = 1000000 

o similares de salida en una máquina de inactividad, y una salida como

Actual clocks per second = 50000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 600000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 530000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 580000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 730000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 730000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 600000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 560000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 600000 
CLOCKS_PER_SEC = 1000000 
Actual clocks per second = 620000 
CLOCKS_PER_SEC = 1000000 

en una máquina ocupada. Dado que clock() mide el tiempo (aproximado) pasado en su programa, parece que lo probó en una máquina ocupada, y su programa solo obtuvo aproximadamente el 60% del tiempo de la CPU.

+5

Si bien esto es técnicamente cierto, dado que la llamada al sistema que está utilizando también respeta que es inútil. – Joshua

-2

Bien duh. No sabes qué tan lejos en el segundo actual comienzas el cronometraje, ¿verdad? Entonces puede obtener cualquier resultado de 1 a CLOCKS_PER_SEC. Pruebe esto en su bucle interno:

int first_time = time(NULL); 
// Wait for timer to roll over before starting clock! 
while(time(NULL) <= first_time) {} 

int first_clock = clock(); 
first_time = time(NULL); 
while(time(NULL) <= first_time) {} 

int second_time = time(NULL); 
int second_clock = clock(); 

cout << "Actual clocks per second = " << (second_clock - first_clock)/(second_time - first_time) << "\n"; 

cout << "CLOCKS_PER_SEC = " << CLOCKS_PER_SEC << "\n"; 

Ver ideone para el código fuente completo. Informa los relojes reales por segundo como 1000000, como era de esperar. (Tuve que reducir el número de iteraciones a 2, de manera que Ideone no tiene tiempo de espera.)

+1

Esto solo explica por qué el primer resultado es incorrecto; no tiene relación con los otros nueve. (A menos que la E/S tome un tercio de segundo por alguna extraña razón) – Hurkyl

+1

@Hurkyl: Cualquiera que sea el motivo, está claro que las dos instrucciones 'cout' tardan alrededor de un tercio de segundo en ejecutarse. Prueba mi versión, si no me crees. – TonyK

+1

No es * claro * - es solo una posibilidad. La otra posibilidad importante es que la discrepancia se debe a que 'reloj 'no mide el tiempo del reloj de pared. El próximo más probable, IMO, es la baja resolución en 'clock' y/o' time'. – Hurkyl

2
  1. CLOCKS_PER_SECOND en POSIX es una constante igual a 1000000.
  2. CLOCKS_PER_SECOND no se supone para mostrar el número de reloj en tu proceso. Es un número de resolución que puede usar para convertir la cantidad de relojes en cantidad de tiempo.(Véase la página del manual para la función de reloj())

Por ejemplo si se calcula:

(second_clock-first_clock)/CLOCKS_PER_SEC

obtendrá el tiempo total entre la primera y la segunda llamada a "reloj() "función.

1

C99 estándar

La única cosa que el C99 N1256 standard draft dice acerca CLOCKS_PER_SEC es que:

CLOCKS_PER_SEC que se expande a una expresión con el tipo clock_t (descrito a continuación) que es el número por segundo del valor devuelto por la función de reloj

Como othe La mención rs, POSIX lo establece en 1 millón, lo que limita la precisión de esto a 1 microsegundo. Creo que esto es solo un valor histórico de los días en los que se midieron las frecuencias máximas de la CPU en Mega Hertz.

Cuestiones relacionadas