2008-09-22 19 views
5

Pracuję nad aplikacją C++, która potrzebuje szczegółowych informacji o taktowaniu, do poziomu milisekund.Czas w C++, milisekundy od ostatniej sekundy

Zamierzamy zebrać czas na drugą dokładność za pomocą standardowej funkcji time() w <ctime>. Chcemy dodatkowo zebrać milisekundy, które upłynęły od ostatniej sekundy podane przez time().

Czy ktoś zna wygodną metodę uzyskiwania tych informacji?

Odpowiedz

-1

Sprawdź metody QueryPerformanceCounter, jeśli są one przeznaczone dla systemu Windows.

8

Nie ma przenośnego rozwiązania tego problemu, ponieważ ANSI C nie definiuje standardowej funkcji czasu z dokładnością do milisekund. Jeśli używasz systemu Windows, możesz użyć funkcji GetTickCount(), timeGetTime() lub QueryPerformanceCounter()/QueryPerformanceFrequency(). Należy pamiętać, że mają one różne dokładności i różne koszty runtime.

Istnieją inne podobne funkcje w innych systemach operacyjnych; Nie jestem pewien, co oni są z mojej głowy.

0

Wszystko, czego nie ma w nagłówku (c)time.h, wymaga specyficznych dla systemu operacyjnego metod. Uważam, że wszystkie te metody są drugą rozdzielczością.

W jakim systemie operacyjnym pracujesz?

11

Boost.DateTime ma reprezentacje milisekundy i nanosekundy IF podstawowa platforma obsługuje je. Mimo że używa kodu specyficznego dla platformy, zachowuje te dane poza kodem.

Jeśli to wielka sprawa, mają inny sposób robienia niezależnej od platformy rozdzielczości podsekcji. This page Kilka akapitów na dole mówi o tym, jak to zrobić.

(ze strony)

Na przykład, załóżmy, chcemy skonstruować za pomocą licznika, który reprezentuje dziesiątych sekundy. Oznacza to, że każde tiknięcie wynosi 0,1 sekundy.

int number_of_tenths = 5; 
//create a resolution independent count -- divide by 10 since there are 
//10 tenths in a second. 
int count = number_of_tenths*(time_duration::ticks_per_second()/10); 
time_duration td(1,2,3,count); //01:02:03.5 //no matter the resolution settings 
2

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. Pokaże liczbę cykli procesora wykonanych od momentu uruchomienia procesora. Jest to prawdopodobnie najdoskonalszy licznik, jaki można uzyskać w celu pomiaru wydajności.

Należy zauważyć, że jest to liczba cykli procesora. Na Linuksie możesz uzyskać prędkość procesora z/proc/cpuinfo i podzielić, aby uzyskać liczbę sekund. Przekształcenie tego w podwójne jest bardzo przydatne.

Gdy uruchomię to na moim polu, mam

 
11867927879484732 
11867927879692217 
it took this long to call printf: 207485 

Oto Intel developer's guide, który daje mnóstwo szczegółów.

#include <stdio.h> // stackoverflow bug: pre tag eats the filenames, 
#include <stdint.h> // so i had to put spaces in the angle brackets 

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); 
} 
+1

Dyspozycja RDTSC jest zalecane, ponieważ może dać błędne wyniki, jeśli CPU przechodzi w stan uśpienia, a także nie wytwarza spójnych wyników między rdzeniami systemu wielordzeniowych. –

+1

Te problemy dotyczą również QueryPerformanceTimer - http://www.virtualdub.org/blog/pivot/entry.php?id=106 – yrp

+1

QueryPerformanceCounter() w systemie Vista z HPET nie ma tych problemów, ani nie jest włączony XP z/USEPMTIMER. AMD oferuje sterownik procesora, który poprawia synchronizację QPC() w XP. Korzystanie z RDTSC bezpośrednio uniemożliwia korzystanie z tych ulepszeń. – bk1e

1

Jeśli jesteś na systemie Unix, gettimeofday() powróci sekund i mikrosekund , aż do rozdzielczości zegara systemowego.

int gettimeofday(struct timeval *tv, struct timezone *tz); 

struct timeval { 
    time_t  tv_sec;  /* seconds */ 
    suseconds_t tv_usec; /* microseconds */ 
}; 
1
#include <ctime> 

clock_t elapsed = static_cast<double>(clock()/CLOCKS_PER_SEC); 

upływie będzie upływie czasu procesora, w ciągu kilku sekund.

Rozdzielczość zależy od systemu operacyjnego, ale na ogół jest lepsza niż w milisekundach dla większości systemów.

-1

Intel Threading Building Blocks library posiada funkcję, ale TBB jest obecnie tylko one dostępne na Intel i klonów (to znaczy, że nie jest dostępny na SPARC, PowerPC, ARM, itp)

+0

Wow, głosowanie w dół sześć lat po udzieleniu odpowiedzi na pytanie, ale bez wyjaśnienia. Niestety, nie wspomniałem o funkcji, o której myślałem; mogło to mieć coś wspólnego z 'tick_count' (https://software.intel.com/en-us/node/506283). W dzisiejszych czasach używałbym funkcji w '' (http://en.cppreference.com/w/cpp/chrono). –

2

Jako inny powiedział, nie ma nie jest to przenośny sposób na zrobienie tego.

Co robię (w msvC++ i linux/g ++) używam klasy, która używa QueryPerformanceCounter w systemie Windows i gettimeofday na Linux. Jest to klasa czasowa, która może zapewnić Ci czas pomiędzy dwoma połączeniami. Możesz go zmodyfikować zgodnie ze swoimi potrzebami.

#if defined(_MSC_VER) 
# define NOMINMAX // workaround un bug dans windows.h qui define des macros 
        // "min" et "max" qui entrent en conflit avec la STL. 
# include <windows.h> 
#else 
# include <sys/time.h> 
#endif 

namespace Utils 
{ 

    /** 
    * Implémente un chronométre qui mesure le temps etre deux appels. 
    */ 
    class CTimer 
    { 
    private: 
#  if defined(_MSC_VER) 
     LARGE_INTEGER m_depart; 
#  else 
     timeval m_depart; 
#  endif 

    public: 
     /** 
     * Démarre le timer. 
     * 
     * Cette fonction sert à démarrer le timer. Si le timer est déja 
     * démarrer, elle le redémarre simplement. 
     */ 
     inline void start() 
     { 
#  if defined(_MSC_VER) 
      QueryPerformanceCounter(&m_depart); 
#  else 
      gettimeofday(&m_depart, 0); 
#  endif 

     }; 

     /** 
     * Retourne le nombre de secondes depuis le départ du timer. 
     * 
     * @return Nombre de secondes écoulés depuis le départ du timer 
     */ 
     inline float GetSecondes() const 
     { 
#  if defined(_MSC_VER) 
      LARGE_INTEGER now; 
      LARGE_INTEGER freq; 

      QueryPerformanceCounter(&now); 
      QueryPerformanceFrequency(&freq); 

      return (now.QuadPart - m_depart.QuadPart)/static_cast<float>(freq.QuadPart); 
#  else 
      timeval now; 
      gettimeofday(&now, 0); 

      return now.tv_sec - m_depart.tv_sec + (now.tv_usec - m_depart.tv_usec)/1000000.0f; 
#  endif 
     }; 
    }; 
} 
Powiązane problemy