Je gettimeofday () zaručeno, že rezoluce mikrosekundy?

hlasů
82

Jsem portování hru, která byla původně napsána pro Win32 API, na Linuxu (dobře, portování port OS X portu Win32 do Linux).

Jsem implementoval QueryPerformanceCountertím, že se uSeconds protože tento proces nastartovat:

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, spolu s QueryPerformanceFrequency()dává konstantní 1000000 jako frekvence, funguje dobře na mém počítači , takže mi 64 bitovou proměnnou, která obsahuje uSecondsod startu programu.

Takže je to přenosné? Nechci odhalit to funguje jinak, pokud jádro byl sestaven určitým způsobem nebo něco podobného. Jsem spokojen s tím, že nepřenosné na jinou hodnotu než Linux, nicméně.

Položena 01/08/2008 v 15:36
zdroj uživatelem
V jiných jazycích...                            


10 odpovědí

hlasů
54

Možná. Ale máte větší problémy. gettimeofday()může mít za následek nesprávné časování, pokud existují procesy ve vašem systému, které mění časovač (tj ntpd). Na „normální“ linux, i když jsem přesvědčen, že řešení gettimeofday()je 10us. To může vyskočit dopředu a dozadu a času, tedy na základě procesy běžící na vašem systému. Toto účinně dělá odpověď na vaši otázku ne.

Měli byste se podívat na clock_gettime(CLOCK_MONOTONIC)pro načasování intervalů. To trpí několika menších problémech kvůli věcem, jako jsou multi-core systémy a externími nastavení hodin.

Také, podívejte se do clock_getres()funkce.

Odpovězeno 01/08/2008 v 15:53
zdroj uživatelem

hlasů
39

High Resolution, Low Overhead časování pro procesory Intel

Pokud jste na hardware Intel, tady je návod, jak číst CPU v reálném čase instrukční čítač. To vám řekne, počet CPU cyklů provedených od roku procesor byl spuštěn. To je pravděpodobně nejlepší zrnitá counter můžete získat pro měření výkonnosti.

Všimněte si, že se jedná o počet cyklů CPU. Na Linuxu můžete získat rychlost procesoru z / proc / cpuinfo a dělit se dostat počet sekund. Převedení do dvojnásobku je docela šikovný.

Když spustím to na svém poli, mám

11867927879484732
11867927879692217
it took this long to call printf: 207485

Zde je průvodce Intel vývojáře , který dává spoustu detailů.

#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);
}
Odpovězeno 02/08/2008 v 09:08
zdroj uživatelem

hlasů
18

@Bernard:

Musím se přiznat, že většina vašich například šel přímo nad mou hlavou. To dělá kompilace, a zdá se, pracuje, ačkoli. Je to bezpečné pro SMP systémy nebo SpeedStep?

To je dobrá otázka ... Myslím, že kód je v pořádku. Z praktického hlediska, můžeme ji použít v mé společnosti každý den, a narazíme na poměrně širokou škálu boxů, vše od 2-8 jader. Samozřejmě, YMMV, etc, ale zdá se, že je spolehlivý a low-režijní (protože to neznamená, že přepnutí kontextu do systému prostoru) metody časování.

Obecně platí, jak to funguje, je:

  • prohlásit, že blok kódu být assembler (a těkavé, tak pro optimalizaci jej nechat být).
  • vykonat instrukci CPUID. Kromě získání nějaké informace o procesoru (což neuděláme nic s) synchronizuje spuštění vyrovnávací paměti CPU tak, aby časování nejsou ovlivněny out-of-order provedení.
  • spustit rdtsc (číst časové razítko) provedení. To načte počet strojových cyklů provedených od procesoru se resetuje. Jedná se o 64-bitová hodnota, tak se současnými rychlostmi CPU bude zábal kolem každých 194 let nebo tak. Je zajímavé, že v původním odkazem Pentium, ale na vědomí, že se zalomí kolem každých 5800 let nebo tak.
  • Posledních pár řádků ukládat hodnoty z registrů do proměnných HI a LO, a dej to do návratové hodnoty 64-bit.

Zvláštní poznámky:

  • out-of-objednávat popravy může způsobit nesprávné výsledky, takže jsme se spustit „CPUID“ instrukce, které kromě dává vám nějaké informace o CPU také synchronizuje žádnou out-of-order provádění instrukcí.

  • Většina operační systémy synchronizovat počítadla na CPU, kdy začnou, takže odpověď je dobré během několika nano-sekund.

  • Spánkem komentář je asi pravda, ale v praxi pravděpodobně nezajímá časování napříč hibernace hranice.

  • ohledně speedstep: Novější Intel procesory kompenzovat změny rychlosti a vrátí upravenou počítat. Udělal jsem rychlý sken přes některé z polí v naší síti a našel jen jeden čtvereček, který neměl to: Pentium 3 běží nějaké staré databázový server. (Jedná se o linux boxy, takže jsem zkontrolovány: grep constant_tsc / proc / cpuinfo)

  • Nejsem si jistý, o AMD CPU, jsme primárně Intel shop, i když vím, že někteří z našich systémů guru low-level dělal vyhodnocení AMD.

Doufám, že to uspokojí vaši zvědavost, je to zajímavý a (IMHO) pod zkoumané oblasti programování. Víte, kdy Jeff a Joel mluvili o tom, zda má či nemá programátor vědět, C? na ně jsem křičel, „hej zapomenout, že high-level C věci ... assembler je to, co byste měli naučit, pokud chcete vědět, co je počítač dělá!“

Odpovězeno 04/08/2008 v 01:51
zdroj uživatelem

hlasů
14

Také by vás mohlo zajímat Linux dotazy týkajícíclock_gettime(CLOCK_REALTIME)

Odpovězeno 18/08/2008 v 16:51
zdroj uživatelem

hlasů
11

Víno je vlastně používat gettimeofday () implementovat QueryPerformanceCounter () a je známo, aby se mnoho her pro Windows pracují na Linux a Mac.

začíná http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

vede k http://source.winehq.org/source/dlls/ntdll/time.c#L448

Odpovězeno 04/08/2008 v 15:44
zdroj uživatelem

hlasů
9

Tak to říká mikrosekund explicitně, ale říká, že řešení systémových hodin není specifikována. Myslím, že rozlišení v tomto kontextu znamená, jak se nejmenší množství bude někdy být zvýšena?

Struktura dat je definován tak, že mikrosekund jako jednotka měření, ale neznamená to, že hodiny nebo operační systém je ve skutečnosti schopen měřit, že jemně.

Stejně jako ostatní lidé navrhli, gettimeofday()je špatné, protože nastavením času může způsobit hodiny překroutit a shodit svůj výpočet. clock_gettime(CLOCK_MONOTONIC)je to, co chcete, a clock_getres()bude ti přesnost vaší hodiny.

Odpovězeno 02/08/2008 v 18:57
zdroj uživatelem

hlasů
8

Skutečné rozlišení gettimeofday () závisí na hardwarové architektury. Procesory Intel, stejně jako SPARC stroje nabízejí vysokou časovače rozlišením, které měří mikrosekund. Další hardwarové architektury klesnout zpět na časovači v systému, který je obvykle nastavena na 100 Hz. V takových případech je časové rozlišení bude méně přesné.

Získal jsem tuto odpověď od High Resolution Měření časů a časovače, část I.

Odpovězeno 01/08/2008 v 15:55
zdroj uživatelem

hlasů
5

Tato odpověď se zmiňuje problémy s časem bylo upraveno. Oba vaše problémy zaručující klíště jednotek a problémy s časem jsou upraveny jsou řešeny v C ++ 11 s <chrono>knihovnou.

Hodiny std::chrono::steady_clockje zaručena není třeba upravit, a dále bude postupovat při konstantní rychlosti vzhledem k reálném čase, takže technologie, jako jsou SpeedStep musí ji neovlivní.

Můžete získat typesafe jednotky převodem na jeden z std::chrono::durationoborů, jako je například std::chrono::microseconds. U tohoto druhu neexistuje dvojznačnost jednotek používaných hodnotou klíštěte. Nicméně, mějte na paměti, že hodiny nemusí nutně mít toto usnesení. Můžete převést trvání na attoseconds, aniž byste museli hodiny, které přesné.

Odpovězeno 26/06/2012 v 16:57
zdroj uživatelem

hlasů
4

Z mé zkušenosti, az toho, co jsem četl přes internet, odpověď je „Ne,“ to není zaručeno. Záleží na rychlosti procesoru, operační systém, chutí Linux, atd

Odpovězeno 01/08/2008 v 15:46
zdroj uživatelem

hlasů
3

Čtení RDTSC není spolehlivá v SMP systémy, protože každý procesor udržuje svůj vlastní pult a každý čítač není zaručeno synchronizovat s ohledem na jiný procesor.

I by se mohlo zdát snaží clock_gettime(CLOCK_REALTIME). POSIX příručka ukazuje, že by to mělo být realizován na všech kompatibilních systémů. To může poskytnout počet nanosecond, ale pravděpodobně se bude chtít podívat clock_getres(CLOCK_REALTIME)na váš systém, aby zjistili, co skutečné rozlišení.

Odpovězeno 18/08/2008 v 16:40
zdroj uživatelem

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