Czy gettimeofday () gwarancją od mikrosekund?

głosy
82

Ja portowania gry, że dla Win32 API została pierwotnie napisana, aby Linux (dobrze, przyłączeniowym portu OS X portu Win32 do Linux).

Mam realizowane QueryPerformanceCounterprzez podanie uSeconds ponieważ proces uruchamiania:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

To, w połączeniu z QueryPerformanceFrequency()dając stałą 1000000 jak częstotliwość, działa dobrze na moim komputerze , dając mi zmiennej 64 bitowej, który zawiera uSecondsod programu rozruchu.

Więc jest to przenośne? Nie chcę, aby dowiedzieć się, że działa inaczej jeśli kernel został skompilowany w określony sposób lub coś podobnego. Jestem w porządku to jest non-przenośny na coś innego niż Linux, jednak.

Utwórz 01/08/2008 o 15:36
źródło użytkownik
W innych językach...                            


10 odpowiedzi

głosy
54

Może. Ale masz większe problemy. gettimeofday()może doprowadzić do błędnych taktowania jeśli istnieją procesy w systemie, które zmieniają timera (tzn ntpd). Na „normalnym” Linux, choć uważam, że uchwała gettimeofday()jest 10us. To może skoczyć do przodu i do tyłu oraz czas, w związku z tym, na podstawie procesów uruchomionych w systemie. To skutecznie sprawia, że odpowiedź na pytanie nr.

Należy przyjrzeć się clock_gettime(CLOCK_MONOTONIC)dla przedziałów czasowych. Cierpi ona z kilku mniejszych problemów z powodu rzeczy, takich jak systemy wielordzeniowe i zewnętrznych ustawień zegara.

Również zajrzeć do clock_getres()funkcji.

Odpowiedział 01/08/2008 o 15:53
źródło użytkownik

głosy
39

High Resolution, Overhead Niska Timing dla procesorów Intel

Jeśli jesteś na sprzęcie Intel, oto jak do zapoznania się z procesora w czasie rzeczywistym licznik instrukcji. powie to liczbę cykli procesora wykonana ponieważ procesor został uruchomiony. Jest to prawdopodobnie najlepsza drobnoziarnisty licznik można dostać do pomiaru wydajności.

Należy pamiętać, że jest to liczba cykli procesora. Na Linuksie można uzyskać szybkość procesora z / proc / cpuinfo i podzielić się uzyskać liczbę sekund. Konwersja to do podwójnego jest bardzo przydatny.

Gdy uruchomię to na moim oknie, otrzymuję

11867927879484732
11867927879692217
it took this long to call printf: 207485

Oto przewodnik Intel dewelopera , który daje mnóstwo szczegółów.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}
Odpowiedział 02/08/2008 o 09:08
źródło użytkownik

głosy
18

@Bernard:

Muszę przyznać, że większość przykład poszedł prosto na głowę. Czyni kompilacji i wydaje się działać, choć. Czy to bezpieczne dla systemów SMP lub SpeedStep?

To dobre pytanie ... Myślę, że ok kod użytkownika. Z praktycznego punktu widzenia, możemy używać go w mojej firmie na co dzień, a my uruchomić na dość szeroką gamę skrzynek, wszystko z 2-8 rdzeni. Oczywiście, YMMV, etc, ale wydaje się być niezawodnym i nisko nad głową (bo to nie ma przełącznika kontekstowe do systemu przestrzeni) sposobu odmierzania czasu.

Ogólnie, jak to działa to:

  • zadeklarować blok kodu być assembler (i lotny, więc optymalizator go zostawić w spokoju).
  • wykonanie instrukcji CPUID. Oprócz coraz informacje procesora (co nie mamy nic z robić) synchronizuje bufora Wykonawczym CPU tak, że czasy nie są dotknięte realizacją out-of-order.
  • wykonać rdtsc (czytaj datownika) wykonanie. To pobiera liczbę cykli maszynowych wykonane, ponieważ procesor został zresetowany. Jest to 64-bitowa wartość, więc z obecnych prędkościach procesora będzie owinąć wokół co 194 lat lub więcej. Co ciekawe, w pierwotnym odniesieniem Pentium, zauważają, że otacza co 5800 lat.
  • Ostatnia para linii przechowywać wartości z rejestrów do zmiennych HI i LO, i umieścić, że do wartości zwracanej 64-bitowym.

Szczególne uwagi:

  • wykonywanie poza kolejnością może być przyczyną nieprawidłowych wyników, więc wykonujemy „CPUID” Instrukcja które oprócz daje pewne informacje o CPU synchronizuje również wykonanie dowolnego out-of-order obsługi.

  • Większość systemów operacyjnych zsynchronizować liczniki na procesorach kiedy zaczynają, więc odpowiedź jest dobra, aby w ciągu kilku nanosekund.

  • Komentarz hibernacji to chyba prawda, ale w praktyce prawdopodobnie nie obchodzi taktowania ponad granicami hibernacji.

  • dotyczące SpeedStep: Nowsze procesory Intel skompensowania zmian prędkości i zwraca skorygowanej liczby. Zrobiłem szybkie skanowanie nad niektórych pól w naszej sieci i znaleźć tylko jedno pole, które nie mają go: Pentium 3 uruchomiony niektóre starego serwera bazy danych. (Są to pudełka linux, więc sprawdziłem z: grep constant_tsc / proc / cpuinfo)

  • Nie jestem pewien co do AMD, jesteśmy przede wszystkim sklep Intel, chociaż wiem, że niektórzy z naszych systemów guru niskopoziomowych zrobił ocenę AMD.

Nadzieję, że to zaspokaja swoją ciekawość, jest to ciekawe i (IMHO) w przebadanym obszarze programowania. Wiesz, kiedy Jeff i Joel rozmawiali o tym, czy programista powinien wiedzieć, C? I krzyczał na nich, „hej zapominać, że wysoki poziom C rzeczy ... assembler jest to, co powinno się nauczyć, jeśli chcesz wiedzieć, co komputer robi!”

Odpowiedział 04/08/2008 o 01:51
źródło użytkownik

głosy
14

Może być zainteresowany w Linux FAQclock_gettime(CLOCK_REALTIME)

Odpowiedział 18/08/2008 o 16:51
źródło użytkownik

głosy
11

Wino jest rzeczywiście przy gettimeofday () w celu wdrożenia QueryPerformanceCounter (), a wiadomo, aby wiele gier systemu Windows działa na Linux i Mac.

rozpoczyna http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

prowadzi do http://source.winehq.org/source/dlls/ntdll/time.c#L448

Odpowiedział 04/08/2008 o 15:44
źródło użytkownik

głosy
9

Tak mówi mikrosekund wyraźnie, ale mówi, że rozdzielczość zegara systemowego jest nieokreślona. Przypuszczam rozdzielczość oznacza w tym kontekście jak najmniejsza kwota zostanie kiedykolwiek zwiększany?

Struktura danych jest zdefiniowany jako mający mikrosekund jako jednostkę miary, ale to nie znaczy, że zegar czy system operacyjny jest faktycznie zdolne do pomiaru, które subtelnie.

Podobnie jak inni sugerują, gettimeofday()jest złe, ponieważ ustawienie czasu może powodować zegar pochylać i zrzucić swoje obliczenia. clock_gettime(CLOCK_MONOTONIC)jest to, co chcesz, i clock_getres()powie ci dokładność zegara.

Odpowiedział 02/08/2008 o 18:57
źródło użytkownik

głosy
8

Rzeczywista rozdzielczość gettimeofday () zależy od architektury sprzętowej. procesory Intel, jak również maszyny SPARC oferują wysokiej rozdzielczości, które mierzą zegary mikrosekundy. Innych architekturach sprzętowych spaść z powrotem do zegara systemowego, który jest zazwyczaj ustawiony na 100 Hz. W takich przypadkach, rozdzielczość czasowa będzie mniej dokładne.

Zdobyłem tę odpowiedź od High Resolution czas pomiaru i timery, część I

Odpowiedział 01/08/2008 o 15:55
źródło użytkownik

głosy
5

Ta odpowiedź wymienia problemy z zegarem jest regulowana. Zarówno twoje problemy gwarantujące jednostek zaznaczyć i problemy z czasem są dostosowane są rozwiązywane w C ++ 11 z <chrono>biblioteki.

Zegar std::chrono::steady_clocknie jest gwarantowana być regulowane, a ponadto będzie on awansować ze stałą prędkością względem czasie rzeczywistym, tak jak technologie SpeedStep nie musi wpływać na to.

Można dostać jednostek typesafe poprzez konwersję do jednego z std::chrono::durationspecjalności, takich jak std::chrono::microseconds. Z tego typu nie ma niejednoznaczności o jednostkach używanych przez wartość kleszcza. Jednak należy pamiętać, że zegar nie musi mieć tej uchwały. Można konwertować trwa do attosekund bez posiadania zegar, który dokładne.

Odpowiedział 26/06/2012 o 16:57
źródło użytkownik

głosy
4

Z mojego doświadczenia wynika, iz tego co czytałem w internecie, odpowiedź brzmi „nie”, to nie jest gwarantowane. To zależy od szybkości procesora, system operacyjny Linux, smak itp

Odpowiedział 01/08/2008 o 15:46
źródło użytkownik

głosy
3

Czytając RDTSC nie jest niezawodny w systemach SMP, ponieważ każdy CPU utrzymuje swój własny licznik i każdy licznik nie jest gwarantowane przez zsynchronizowane w odniesieniu do innego procesora.

I może sugerować próbuje clock_gettime(CLOCK_REALTIME). Instrukcja POSIX wskazuje, że powinno to być realizowane na wszystkich systemach zgodnych. Może on stanowić liczbę nanosekund, ale prawdopodobnie będzie chciał sprawdzić clock_getres(CLOCK_REALTIME)w systemie, aby zobaczyć, co rzeczywista rozdzielczość to.

Odpowiedział 18/08/2008 o 16:40
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more