2012-05-04 6 views
20

Właśnie napisałem ten krótki program C++, aby zbliżyć rzeczywistą liczbę taktów zegara na sekundę.Dlaczego CLOCKS_PER_SEC nie jest faktyczną liczbą zegarów na sekundę?

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

} 

Po uruchomieniu programu otrzymuję wynik podobny do tego.

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 

Dlaczego nie rzeczywista liczba zegar tyka za drugim meczu z CLOCKS_PER_SEC? Nie są nawet w przybliżeniu równe. Co tu się dzieje?

+3

Pamiętaj, że możesz używać pętli przez mniej niż sekundę. Jeśli wywołasz 'time' i pozostanie 200ms przez następną sekundę, będziesz pętli ~ 200ms. W każdym razie nie jest to prawdopodobnie główny problem. – mfontanini

+0

Dobrze, zdaję sobie sprawę, że to jest powód, dla którego pierwsza iteracja pętli zwraca mniejszy wynik niż kolejne iteracje. Ale moje pytanie dotyczy kolejnych iteracji. Chyba powinienem to wyjaśnić. –

+0

Teraz nadal dostajesz naprzód swój cout w każdej kolejnej iteracji. Zaczekaj, aż zaczniesz na sekundę przed rozpoczęciem pomiaru. – David

Odpowiedz

24

clock zwraca ilość czasu spędzonego w twoim programie. Istnieje 1 000 000 taktów zegara na sekundę łącznie *. Wygląda na to, że Twój program pochłonął 60% z nich.

Coś jeszcze wykorzystało pozostałe 40%.

* porządku, są praktycznie 1000000 zegara kleszczy na sekundę. Rzeczywista liczba jest znormalizowana, więc Twój program postrzega 1 000 000 tyknięć.

17

Od strony człowieka z clock(3):

POSIX wymaga CLOCKS_PER_SEC równe 1000000, niezależnie od rzeczywistej rozdzielczości.

Twoje wdrożenie wydaje się zgodne z POSIX przynajmniej pod tym względem.

uruchomić program tutaj, mam

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 

lub podobny wynik na bezczynności urządzenia, a wyjście jak

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 

na ruchliwej maszyny. Ponieważ clock() mierzy (przybliżony) czas spędzony w twoim programie, wydaje się, że testowałeś na obciążonym komputerze, a twój program dostał tylko około 60% czasu procesora.

+5

Chociaż jest to technicznie prawdziwe, ponieważ wywołanie systemowe, z którego korzysta, uwzględnia również to, że jest to bezużyteczne. – Joshua

-2

Well duh. Nie wiesz, jak daleko do obecnego momentu zaczynasz wyczucie czasu, prawda? Możesz więc uzyskać dowolny wynik od 1 do CLOCKS_PER_SEC. Spróbuj tego w wewnętrznej pętli:

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"; 

Zobacz ideone na pełnym kodem źródłowym. Raportuje rzeczywiste zegary na sekundę jako 1000000, jak można się spodziewać. (Miałem do zmniejszenia liczby iteracji 2, tak że ideone nie czas na przygotowania.)

+1

Wyjaśnia to tylko, dlaczego pierwszy wynik jest nieprawidłowy; nie ma to wpływu na pozostałe dziewięć. (chyba że I/O zajmuje jedną trzecią sekundy z jakiegoś dziwnego powodu) – Hurkyl

+1

@Hurkyl: Bez względu na przyczynę, jasne jest, że dwie instrukcje 'cout' zajmują około jednej trzeciej sekundy. Wypróbuj moją wersję, jeśli mi nie wierzysz. – TonyK

+1

To nie jest * jasne * - to tylko możliwość. Inną ważną możliwością jest to, że rozbieżność wynika z "zegara", który nie mierzy czasu zegarowego. Kolejnym najprawdopodobniej IMO jest niska rozdzielczość na 'clock' i/lub' time'. – Hurkyl

2
  1. CLOCKS_PER_SECOND w POSIX jest stałą równą 1000000.
  2. CLOCKS_PER_SECOND nie ma pokazać liczbę zegar w twoim procesie. Jest to numer rozdzielczości, który można wykorzystać do zamiany liczby zegarów na ilość czasu.(Patrz strony man zegara function())

Na przykład, jeśli obliczyć:

(second_clock-first_clock)/CLOCKS_PER_SEC

otrzymasz całkowity czas pomiędzy pierwszym i drugim wezwanie do „zegarowego() "funkcja.

1

C99 standardowy

Jedyne C99 N1256 standard draft mówi o CLOCKS_PER_SEC jest to, że:

CLOCKS_PER_SEC która rozwija się do wyrażenia z typem clock_t (opisane poniżej), który jest numerem na sekundę wartości zwróconej przez funkcję zegara

Podobnie jak inne Wspomina się, POSIX ustawia go na 1 milion, co ogranicza dokładność tego do 1 mikrosekundy. Myślę, że jest to tylko wartość historyczna z dni, w których maksymalne częstotliwości procesora były mierzone w Mega Hertz.

Powiązane problemy