2010-02-19 15 views

Odpowiedz

4

Do takich sytuacji wprowadziłem już zegar: faktycznie skończyłem z klasą z dwiema różnymi implementacjami, jedną dla Windows i jedną dla POSIX.

Powodem było to, że system Windows ma funkcję QueryPerformanceCounter(), która daje dostęp do bardzo dokładnego zegara, który idealnie nadaje się do taktowania.

W systemie POSIX nie jest to jednak możliwe, dlatego właśnie użyłem klas boost.datetime do przechowywania czasu początkowego i końcowego, a następnie obliczyłem czas ich trwania. Oferuje on zegar "wysokiej rozdzielczości", ale rozdzielczość jest nieokreślona i różni się w zależności od platformy.

1

wysoce precyzyjne czasomierze są specyficzne dla platformy i tak nie są określone przez standard C++, ale istnieją bibliotek dostępne. Zobacz dyskusję na temat this question.

0

Może to być problem zależny od systemu operacyjnego, a nie problem językowy.

Jeśli jesteś w systemie Windows, możesz uzyskać dostęp do milisekund od 10 do 16-milisekundowego licznika czasu przez GetTickCount() lub GetTickCount64(). Po prostu wywołaj go raz na początku i raz na końcu, i odejmij.

To było to, czego użyłem wcześniej, jeśli dobrze pamiętam. Połączona strona ma również inne opcje.

+0

Does GetTickCount()() użyć QueryPerformanceCounter pod maską lub? – Mithrax

+0

Tego nie wiem. Dodałem link do strony GetTickCount() i wygląda na to, że masz inne, prawdopodobnie lepsze opcje oparte na tym, co tam jest. – John

+0

Nie. GetTickCount() jest niedokładny. Jeśli chcesz dokładnej liczby, należy użyć QueryPerformanceCounter() (EDIT: przez niedokładne Znaczy +/- 10ms) –

0
#include <time.h> 

clock_t start, end; 
start = clock(); 
//Do stuff 
end = clock(); 

printf("Took: %f\n", (float)((end - start)/(float)CLOCKS_PER_SEC)); 
+0

To działałoby, ale rozdzielczość będzie słaba. –

+0

To faktycznie nie działa do pomiaru czasu bezwzględnego, ponieważ 'clock()' zwraca tylko czas procesora, który ** Twój ** kod wziął. Dlatego jeśli zastąpisz '\\ Do stuff '' 'usleep (1000000)' printf zwróci 0.0000 sekund zamiast 1 sekundy. – CodingAway

3

Używam własnej wersji funkcji Pythona time_it. Zaletą tej funkcji jest to, że powtarza ona obliczenia tyle razy, ile potrzeba, aby uzyskać znaczące wyniki. Jeśli obliczenia są bardzo szybkie, będą powtarzane wiele razy. Na koniec uzyskasz średni czas wszystkich powtórzeń. Nie używa żadnych niestandardowych funkcjonalności:

#include <ctime> 

double clock_diff_to_sec(long clock_diff) 
{ 
    return double(clock_diff)/CLOCKS_PER_SEC; 
} 

template<class Proc> 
double time_it(Proc proc, int N=1) // returns time in microseconds 
{ 
    std::clock_t const start = std::clock(); 
    for(int i = 0; i < N; ++i) 
     proc(); 
    std::clock_t const end = std::clock(); 
    if(clock_diff_to_sec(end - start) < .2) 
     return time_it(proc, N * 5); 
    return clock_diff_to_sec(end - start) * (1e6/N); 
} 

Poniższy przykład wykorzystuje funkcję time_it mierzyć skuteczność różnych pojemnikach STL:

void dummy_op(int i) 
{ 
    if(i == -1) 
     std::cout << i << "\n"; 
} 

template<class Container> 
void test(Container const & c) 
{ 
    std::for_each(c.begin(), c.end(), &dummy_op); 
} 

template<class OutIt> 
void init(OutIt it) 
{ 
    for(int i = 0; i < 1000; ++i) 
     *it = i; 
} 

int main(int argc, char ** argv) 
{ 
    { 
     std::vector<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "vector: " 
        << time_it(boost::bind(&test<std::vector<int> >, c)) << "\n"; 
    }  
    { 
     std::list<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "list: " 
        << time_it(boost::bind(&test<std::list<int> >, c)) << "\n"; 
    } 
    { 
     std::deque<int> c; 
     init(std::back_inserter(c)); 
     std::cout << "deque: " 
        << time_it(boost::bind(&test<std::deque<int> >, c)) << "\n"; 
    } 
    { 
     std::set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "set: " 
        << time_it(boost::bind(&test<std::set<int> >, c)) << "\n"; 
    } 
    { 
     std::tr1::unordered_set<int> c; 
     init(std::inserter(c, c.begin())); 
     std::cout << "unordered_set: " 
      << time_it(boost::bind(&test<std::tr1::unordered_set<int> >, c)) << "\n"; 
    }  
} 

W przypadku gdy ktoś jest ciekawy tutaj jest wyjście I get (skompilowany z VS2008 w trybie uwalniania):

wektor: 8,7168

lista: 27,776

deque: 91,52

zestaw: 103,04

unordered_set: 29.76

+0

Bardzo interesujące. Zarówno dla funkcji pomiaru czasu, jak i dla wglądu na temat różnych pojemników! Dzięki. – Morlock

+0

@Mlocklock - Dzięki! Zrobiłabym czas z szczyptą soli, 'std :: deque' zachowuje się okropnie w tym teście, ale jestem pewien, że w ogólnym ustawieniu nie jest tak źle. – Manuel

3

Użyłem boost::timer do pomiaru czasu trwania operacji. Zapewnia bardzo łatwy sposób wykonywania pomiarów, a jednocześnie jest niezależny od platformy. Oto przykład:

boost::timer myTimer; 
doOperation(); 
std::cout << myTimer.elapsed(); 

P.S. Aby przezwyciężyć błędy precyzji, byłoby miło zmierzyć operacje, które potrwają kilka sekund. Zwłaszcza, gdy próbujesz porównać kilka alternatyw. Jeśli chcesz zmierzyć coś, co zajmuje bardzo mało czasu, spróbuj umieścić go w pętli. Na przykład uruchomić operację 1000 razy, a następnie podzielić całkowity czas od 1000.

0

można znaleźć użyteczne this klasę.

Korzystanie RAII idiom, drukuje tekst podany w budownictwie gdy destruktor jest nazywany, wypełnienie czasu, który upłynął zastępczy z właściwą wartość.

Przykład zastosowania:

int main() 
{ 
    trace_elapsed_time t("Elapsed time: %ts.\n"); 
    usleep(1.005 * 1e6); 
} 

wyjściowa:

Elapsed time: 1.00509s. 
1

pokornie przedstawić własną micro-benchmarking mini-library (on Github). To bardzo proste - jedyną przewagą nad toczeniem jest to, że ma już kod timera o wysokiej wydajności zaimplementowany dla systemów Windows i Linux, a także usuwa irytujący zestaw znaków.

Wystarczy przekazać funkcję (lub lambda), ile razy powinna ona zostać wywołana w ciągu testu (domyślnie: 1), a liczba przebiegów testowych (domyślnie: 100). Najszybszy rozruch próbny (mierzony w milisekundach ułamkowych) jest zwracana:

// Example that times the compare-and-swap atomic operation from C++11 
// Sample GCC command: g++ -std=c++11 -DNDEBUG -O3 -lrt main.cpp microbench/systemtime.cpp -o bench 
#include "microbench/microbench.h" 

#include <cstdio> 
#include <atomic> 

int main() 
{ 
    std::atomic<int> x(0); 
    int y = 0; 

    printf("CAS takes %.4fms to execute 100000 iterations\n", 
     moodycamel::microbench(
      [&]() { x.compare_exchange_strong(y, 0); }, /* function to benchmark */ 
      100000, /* iterations per test run */ 
      100 /* test runs */ 
     ) 
    ); 

    // Result: Clocks in at 1.2ms (12ns per CAS operation) in my environment 

    return 0; 
} 
Powiązane problemy