2008-09-26 20 views
7

W Win32, istnieje sposób na uzyskanie unikalnej liczby cykli procesora lub czegoś podobnego, które byłoby jednolite dla wielu procesów/języków/systemów/etc.Jak uzyskać liczbę cykli procesora w Win32?

Tworzę niektóre pliki dzienników, ale musimy utworzyć wiele plików dziennika, ponieważ hostujemy środowisko wykonawcze .NET i nie chcę dzwonić z jednego do drugiego, aby się zalogować. W związku z tym myślałem, że po prostu wyprodukuję dwa pliki, połączę je, a następnie posortuję, aby uzyskać spójny harmonogram obejmujący połączenia międzynarodowe.

Jednak GetTickCount nie zwiększa się dla każdego połączenia, więc nie jest to niezawodne. Czy jest lepsza liczba, aby podczas sortowania uzyskiwać połączenia we właściwej kolejności?


Edit: Dzięki @Greg że położył mnie na torze do QueryPerformanceCounter, co załatwiło sprawę.

Odpowiedz

8

Możesz użyć instrukcji procesora RDTSC (zakładając x86). Ta instrukcja podaje licznik cykli procesora, ale należy pamiętać, że wzrośnie ona bardzo szybko do maksymalnej wartości, a następnie zresetuje się do 0. Jak wspomina artykuł w Wikipedii, lepiej być może używając funkcji QueryPerformanceCounter.

12

Heres an interesting article! mówi, aby nie używać RDTSC, ale zamiast tego używać QueryPerformanceCounter.

Wniosek:

Korzystanie regularne stare timeGetTime() zrobić taktowanie nie jest niezawodny od wielu opartych na systemie Windows systemów operacyjnych ponieważ ziarnistość systemu timera może być tak wysokie, jak 10-15 milisekund , co oznacza, że ​​ timeGetTime() jest dokładna tylko do 10-15 milisekund. [Należy zauważyć, że wysoka rozdzielczość graniczna występuje w systemach operacyjnych opartych na NT , takich jak Windows NT, 2000 i XP. Windows 95 i 98 mają tendencję mieć znacznie lepszą szczegółowość, około 1-5 ms.]

Jednak jeśli zadzwonisz timeBeginPeriod(1) na początku programu (i timeEndPeriod(1) na końcu), będzie zazwyczaj timeGetTime() uzyskają dokładność do 1-2 milisekund, i dostarczą ci bardzo dokładnych informacji na temat czasu w zakresie .

Sleep() zachowuje się podobnie; długość czasu, Sleep() rzeczywiście śpi dla idzie ręka w rękę z ziarnistości timeGetTime(), więc po nazywając timeBeginPeriod(1) raz Sleep(1) rzeczywiście spać przez 1-2 milisekund Sleep(2) 2-3, a więc na (zamiast spać w przyrostach tak wysokie, jak 10-15 ms).

Dla większej precyzji czasu (dokładność sub-milisekundy), będziesz prawdopodobnie chciał uniknąć stosując montaż mnemoniczny RDTSC ponieważ jest ciężko skalibrować; zamiast tego należy użyć wartości i QueryPerformanceCounter z dokładnością do mniej niż 10 mikrosekund (0,00001 sekund).

Do prostego czasu, zarówno timeGetTime i QueryPerformanceCounter działa dobrze, i QueryPerformanceCounter jest oczywiście bardziej dokładne. Jednakże, jeśli trzeba zrobić wszelkiego rodzaju „czasowych przerw” (takie jak te niezbędne dla framerate ograniczenie), trzeba być ostrożny siedzieć w pętli wywołującego QueryPerformanceCounter, czekając na to, aby osiągnąć pewien wartość; to będzie pochłonąć 100% swojego procesora. Zamiast rozważać hybrydowy system, gdzie można zadzwonić do spania (1) (nie zapomnij timeBeginPeriod (1) po raz pierwszy!) Ilekroć trzeba przejść więcej niż 1 ms od czasu, a następnie wprowadź tylko QueryPerformanceCounter 100% -busy pętli , aby zakończyć ostatni < 1/1000th z sekundy opóźnienia, czego potrzebujesz. Ten da Ci wyjątkowo dokładne opóźnienia (z dokładnością do 10 mikrosekund), przy bardzo niewielkim obciążeniu procesora przez . Zobacz kod powyżej.

+3

Należy unikać timeBeginPeriod(); wpływa na systemowy harmonogram i może powodować problemy z oszczędzaniem energii. – MSalters

1

Użyj GetTickCount i dodaj kolejny licznik podczas scalania plików dziennika. Nie da ci idealnej sekwencji pomiędzy różnymi plikami dziennika, ale przynajmniej zachowa wszystkie dzienniki z każdego pliku we właściwej kolejności.

+2

Liczba znaczników wydaje się rosnąć wraz z wynikiem milisekundowym, i dlatego potrzebuję czegoś nieco dokładniejszego. –

2

System.Diagnostics.Stopwatch.GetTimestamp() zwraca liczbę cykli procesora od czasu początkowego (może, gdy komputer się uruchomi, ale nie jestem pewien) i nigdy nie widziałem, że nie zwiększyło się między 2 wywołaniami.

Cykle procesora będą specyficzne dla każdego komputera, więc nie będzie można użyć go do scalenia pliku dziennika między 2 komputerami.

+0

Dzięki, zamierzam scalić tylko pliki wyprodukowane na tym samym komputerze w tym samym czasie, więc to zadziała. Teraz muszę tylko dowiedzieć się, co ta metoda faktycznie wywołuje :) –

2

Wyjście RDTSC może zależeć od częstotliwości taktowania zegara rdzenia, która dla nowoczesnych procesorów nie jest ani stała, ani, w maszynie wielordzeniowej, spójna.

Użyj czasu systemowego, a jeśli masz do czynienia z kanałami z wielu systemów, użyj źródła czasu NTP. W ten sposób można uzyskać wiarygodne, spójne odczyty czasu; jeśli narzut jest zbyt duży dla twoich celów, użycie HPET do czasu pracy od ostatniego znanego wiarygodnego odczytu czasu jest lepsze niż użycie samego HPET.

Powiązane problemy