Próbuję użyć time () do pomiaru różnych punktów mojego programu.
Nie rozumiem, dlaczego wartości przed i po są takie same? Rozumiem, że to nie jest najlepszy sposób na profilowanie mojego programu, chcę tylko zobaczyć, jak długo coś potrwa.
printf("**MyProgram::before time= %ld\n", time(NULL));
doSomthing();
doSomthingLong();
printf("**MyProgram::after time= %ld\n", time(NULL));
Próbowałem:
struct timeval diff, startTV, endTV;
gettimeofday(&startTV, NULL);
doSomething();
doSomethingLong();
gettimeofday(&endTV, NULL);
timersub(&endTV, &startTV, &diff);
printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);
Jak odczytać wynik **time taken = 0 26339
? Czy to oznacza 26 339 nanosekund = 26,3 milisekundy?
A co **time taken = 4 45025
to znaczy 4 sekundy i 25 ms?
time()
zwraca inną wartość.time(NULL)
... drugiego wywołania będzie N sekund po pierwszym, a zatem ... innego (chyba że cokolwiek robisz, nie robi t zajmuje sekundę, aby ukończyć ... w takim przypadku będzie taki sam jak pierwszy).Odpowiedzi:
źródło
#include <chrono>
dyrektywę, a ja zmieniłbym czas raportowania jako:std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;
(i nie zapomnieć o c ++ 11 flagę podczas kompilacji:-std=c++11
)time()
Funkcja jest dokładna tylko w ciągu sekundy, ale istniejeCLOCKS_PER_SEC
„zegary” w ciągu sekundy. Jest to łatwy, przenośny pomiar, nawet jeśli jest zbyt uproszczony.źródło
clock()
mierzy czas procesora, a nie upływ czasu rzeczywistego (który może być znacznie większy).Możesz wyodrębnić mechanizm pomiaru czasu i mierzyć czas działania każdej z wywołań przy minimalnym dodatkowym kodzie , po prostu przez wywołanie przez strukturę timera. Dodatkowo w czasie kompilacji można sparametryzować rodzaj taktowania (milisekundy, nanosekundy itp.).
Dzięki recenzji Lokiego Astari i sugestii zastosowania szablonów variadic. To dlatego przekazywane wywołanie funkcji.
Demo
Według komentarza Howarda Hinnanta najlepiej nie uciekać z systemu chronografu, dopóki nie będziemy musieli. Tak więc powyższa klasa może dać użytkownikowi wybór do
count
ręcznego wywołania poprzez dostarczenie dodatkowej metody statycznej (pokazanej w C ++ 14)i przydadzą się najbardziej tym klientom
Pełny kod można znaleźć tutaj . Moja próba zbudowania narzędzia do analizy porównawczej opartej na chrono została tutaj odnotowana .
Jeśli C ++ 17
std::invoke
jest dostępny, wywołanie wywoływanego wexecution
można wykonać w następujący sposób:aby zapewnić kallaby, które są wskaźnikami do funkcji składowych.
źródło
code_timer
), która zajmuje czas rozpoczęcia (std::chrono::system_clock::now();
) w konstruktorze, metodęcode_timer::ellapsed
mierzącą różnicę między nowymnow()
wywołaniem a tym w konstruktorze orazcode_timer::reset
metodę, która resetuje czas rozpoczęcia do nowegonow()
wyniku. Aby zmierzyć wykonanie funktora w moim kodzie, używam darmowej funkcji poza klasą. Pozwala to na pomiar czasu od budowy obiektu do zakończenia wywołania asynchronicznego.chrono
systemu, dopóki nie będziesz musiał (unikaj używania.count()
). Pozwól klientowi zadzwonić,.count()
gdy zostaniesz do tego zmuszony (powiedz dla I / O, co w rzeczywistości jest niefortunne). Klient może chcieć przetworzyć kilka okresów czasu przed wejściem / wyjściem (np. Średnio) i najlepiej to zrobić wchrono
systemie.std::forward<F>(func)
?std::forward<decltype(func)>(func)
ponieważ może mieć zastosowanie do argumentów ogólnej lambdas (auto&& func
), w którychF
nie ma tam składniowo, i łatwo jest ją wyodrębnić za pomocą makra narzędziowego,#define fw(arg) std::forward<decltype(arg)>(arg)
które wykonuję w mojej bibliotece testów porównawczych (więc jest to pozostałość składniowa, na której nie rozwijam zbyt wiele odpowiedź)Jak widzę z twojego pytania, wygląda na to, że chcesz znać upływ czasu po wykonaniu jakiegoś fragmentu kodu. Myślę, że wygodnie byłoby zobaczyć wyniki w sekundach. Jeśli tak, spróbuj użyć
difftime()
funkcji pokazanej poniżej. Mam nadzieję, że to rozwiąże twój problem.źródło
Tylko Windows: (Tag Linux został dodany po opublikowaniu tej odpowiedzi)
Za pomocą GetTickCount () można uzyskać liczbę milisekund, które upłynęły od uruchomienia systemu.
źródło
SleepEx(5000,0)
w miejsce // Wykonaj operację czasochłonne i różnicęafter
ibefore
był prawie 5 sek.time(NULL)
zwraca liczbę sekund, które upłynęły od 01.01.1970 o 00:00 ( Epoka ). Różnica między tymi dwiema wartościami to liczba sekund, które zajęło przetwarzanie.Możesz uzyskać lepsze wyniki
getttimeofday()
, które zwracają bieżący czas w sekundach, podobnie jaktime()
w mikrosekundach.źródło
funkcja czasu (NULL) zwróci liczbę sekund, które upłynęły od 01.01.1970 o 00:00. A ponieważ ta funkcja jest wywoływana w innym czasie w twoim programie, zawsze będzie różna w C ++
źródło
Użycie jest poniżej:
Jest to podobne do zakresu RAII
UWAGA, to nie jest moje, ale myślałem, że ma to znaczenie
źródło
źródło
Wartości wydrukowane przez drugi program to sekundy i mikrosekundy.
źródło
źródło
C ++ std :: chrono ma wyraźną zaletę bycia wieloplatformowym. Jednak wprowadza również znaczny narzut w porównaniu do POSIX clock_gettime (). Na moim Linux-ie wszystkie
std::chrono::xxx_clock::now()
smaki działają mniej więcej tak samo:Chociaż POSIX
clock_gettime(CLOCK_MONOTONIC, &time)
powinien być taki sam jaksteady_clock::now()
ale jest ponad x3 razy szybszy!Oto mój test na kompletność.
Oto wynik, który otrzymuję po kompilacji z gcc7.2 -O3:
źródło
time(NULL)
Wywołanie funkcji zwróci liczbę sekund, które upłynęły od EPOC: 1 stycznia 1970. Może co masz na myśli zrobić, to wziąć różnicę między dwoma znacznikami:źródło
Jak już zauważyli inni, funkcja time () w standardowej bibliotece C nie ma rozdzielczości lepszej niż jedna sekunda. Jedyną w pełni przenośną funkcją C, która może zapewnić lepszą rozdzielczość, wydaje się być clock (), ale raczej mierzy czas procesora niż czas zegara ściennego. Jeśli ktoś chce ograniczyć się do platform POSIX (np. Linux), to funkcja clock_gettime () jest dobrym wyborem.
Od wersji C ++ 11 istnieją znacznie lepsze możliwości pomiaru czasu które oferują lepszą rozdzielczość w formie, która powinna być bardzo przenośna w różnych kompilatorach i systemach operacyjnych. Podobnie biblioteka boost :: datetime zapewnia dobre klasy czasowe wysokiej rozdzielczości, które powinny być wysoce przenośne.
Jednym z wyzwań przy korzystaniu z któregokolwiek z tych urządzeń jest opóźnienie czasowe wprowadzone przez zapytanie zegara systemowego. Od eksperymentowania z clock_gettime (), boost :: datetime i std :: chrono, to opóźnienie może być łatwo kwestią mikrosekund. Tak więc, mierząc czas trwania dowolnej części kodu, musisz pozwolić, aby wystąpił błąd pomiaru mniej więcej tego rozmiaru, lub spróbuj w jakiś sposób poprawić ten błąd zerowy. Najlepiej byłoby zebrać wiele pomiarów czasu zajętych przez funkcję i obliczyć średni lub maksymalny / minimalny czas potrzebny na wiele przebiegów.
Aby pomóc w rozwiązaniu wszystkich problemów związanych z przenośnością i gromadzeniem statystyk, opracowałem bibliotekę cxx-rtimers dostępną na Github, która stara się zapewnić prosty interfejs API dla bloków czasowych kodu C ++, obliczania zerowych błędów i raportowania statystyk z wielu osadzonych timerów w twoim kodzie. Jeśli masz kompilator C ++ 11, po prostu
#include <rtimers/cxx11.hpp>
i użyj czegoś takiego:Po wyjściu z programu otrzymasz podsumowanie statystyk czasowych zapisanych do std :: cerr, takich jak:
który pokazuje średni czas, jego odchylenie standardowe, górną i dolną granicę oraz liczbę wywołań tej funkcji.
Jeśli chcesz korzystać z funkcji czasowych specyficznych dla Linuksa, możesz
#include <rtimers/posix.hpp>
, lub jeśli masz biblioteki Boost, ale starszy kompilator C ++, możesz#include <rtimers/boost.hpp>
. Istnieją również wersje tych klas timerów, które mogą gromadzić statystyczne informacje o taktowaniu z wielu wątków. Istnieją również metody, które pozwalają oszacować błąd zerowy związany z dwoma bezpośrednio kolejnymi zapytaniami zegara systemowego.źródło
Funkcja ta wewnętrznie uzyskuje dostęp do zegara systemowego, dlatego zwraca inne wartości za każdym razem, gdy go wywołujesz. Ogólnie w przypadku języków niefunkcjonalnych w funkcjach może występować wiele efektów ubocznych i ukrytych funkcji, których nie można zobaczyć, patrząc tylko na nazwę funkcji i argumenty.
źródło
Z tego, co widać, tv_sec przechowuje sekundy, które upłynęły, a tv_usec przechowuje mikrosekundy, które upłynęły osobno. I nie są nawzajem konwersjami. Dlatego należy je zmienić na odpowiednią jednostkę i dodać, aby uzyskać całkowity czas, który upłynął.
źródło
W Linuksie clock_gettime () jest jednym z dobrych wyborów. Musisz połączyć bibliotekę czasu rzeczywistego (-lrt).
źródło
Musiałem zmierzyć czas wykonywania poszczególnych funkcji w bibliotece. Nie chciałem kończyć każdego wywołania każdej funkcji funkcją pomiaru czasu, ponieważ jest brzydka i pogłębia stos wywołań. Nie chciałem również umieszczać kodu czasowego na górze i na dole każdej funkcji, ponieważ robi to bałagan, gdy funkcja może wyjść wcześniej lub na przykład zgłasza wyjątki. Skończyło się na zrobieniu timera, który używa własnego czasu życia do mierzenia czasu.
W ten sposób mogę zmierzyć czas ściany bloku kodu, po prostu tworząc instancję jednego z tych obiektów na początku danego bloku kodu (naprawdę funkcja lub dowolny zakres), a następnie pozwalając destruktorowi instancji na pomiar czasu, który upłynął od konstrukcja, gdy instancja wykracza poza zakres. Możesz znaleźć pełny przykład tutaj, ale struktura jest niezwykle prosta:
Struktura oddzwoni na dostarczony funktor, gdy wyjdzie poza zakres, abyś mógł zrobić coś z informacjami o taktowaniu (wydrukować lub zapisać lub cokolwiek innego). Jeśli trzeba zrobić coś jeszcze bardziej skomplikowane można nawet korzystać
std::bind
zstd::placeholders
do callback funkcje z większą liczbą argumentów.Oto szybki przykład użycia:
Jeśli chcesz być bardziej rozmyślny, możesz również użyć
new
idelete
jawnie uruchomić i zatrzymać stoper bez polegania na określaniu zakresu, aby zrobić to za Ciebie.źródło
Są one takie same, ponieważ funkcja doSomething zachodzi szybciej niż ziarnistość timera. Próbować:
źródło
Obie wartości są takie same, ponieważ twoja długa procedura nie trwa tak długo - krócej niż sekundę. Możesz spróbować po prostu dodać długą pętlę (dla (int i = 0; i <100000000; i ++);) na końcu funkcji, aby upewnić się, że to jest problem, a następnie możemy przejść od tego ...
Jeśli powyższe okaże się prawdą, musisz znaleźć inną funkcję systemową (rozumiem, że pracujesz na Linuksie, więc nie mogę ci pomóc z nazwą funkcji), aby dokładniej zmierzyć czas. Jestem pewien, że w Linuksie jest funkcja podobna do GetTickCount (), wystarczy ją znaleźć.
źródło
Zwykle używam następujących:
Jest to to samo, co proponowane przez @ nikos-athanasiou, z tym wyjątkiem, że unikam używania niestałego zegara i używam zmiennej liczby sekund jako czasu trwania.
źródło
high_resolution_clock
jest typedef dla jednegosystem_clock
lub dwóchsteady_clock
. Aby prześledzić, żestd::conditional
jeśliis_steady
część jest prawdziwa, to wybierz to,high_resolution_clock
co jest (typedef do)steady_clock
. Jeśli to fałsz, wybierzsteady_clock
ponownie. Po prostu użyjsteady_clock
od początku ...high_resolution_clock may be a synonym for system_clock or steady_clock
. Powód jest następujący:high_resolution_clock
reprezentuje zegary z najkrótszym okresem tykania, więc niezależnie od implementacji, ma dwie możliwości, jest stabilny lub nie. Jakikolwiek wybór dokonamy, powiedzenie, że implementacja będzie się różnić od pozostałych dwóch zegarów, jest jak powiedzenie, że mamy lepszą implementację dla stałego (lub nie) zegara, którego zdecydujemy się nie używać (dla stałych lub nie). Wiedząc, jak dobrze, wiedząc, dlaczego lepiejW odpowiedzi na trzy szczegółowe pytania OP .
„Nie rozumiem, dlaczego wartości przed i po są takie same? ”
Pierwsze pytanie i próbki kodu pokazuje, że
time()
ma rozdzielczość 1 sekundę, więc odpowiedź musi być tak, że dwie funkcje wykonywane w mniej niż 1 sekundę. Ale od czasu do czasu poinformuje (najwyraźniej nielogicznie) o 1 sekundzie, jeśli dwa znaki timera przekraczają jedną sekundę.W następnym przykładzie użyto
gettimeofday()
wypełnienia tej strukturya drugie pytanie brzmi : „Jak odczytać wynik
**time taken = 0 26339
? Czy to oznacza 26 339 nanosekund = 26,3 ms?”Moja druga odpowiedź to czas zajęty to 0 sekund i 26339 mikrosekund, czyli 0,026339 sekund, co dowodzi, że pierwszy przykład działa w czasie krótszym niż 1 sekunda.
Trzecie pytanie pyta: „A co
**time taken = 4 45025
, to znaczy, 4 sekundy i 25 ms?”Moja trzecia odpowiedź to 4 sekundy i 45025 mikrosekund, czyli 4,045025 sekund, co pokazuje, że OP zmienił zadania wykonywane przez dwie funkcje, które wcześniej mierzył.
źródło
Podobny przykład do tego tutaj dostępnego, tylko z dodatkową funkcją konwersji + wydruku.
źródło
Utworzyłem klasę do automatycznego pomiaru upływu czasu. Sprawdź kod (c ++ 11) w tym linku: https://github.com/sonnt174/Common/blob/master/time_measure.h
Przykład użycia klasy TimeMeasure:
źródło
Matlab
przyprawiony!tic
uruchamia stoper w celu pomiaru wydajności. Funkcja rejestruje czas wewnętrzny przy wykonywaniu polecenia tic. Wyświetlaj upływający czas za pomocątoc
funkcji.źródło
Możesz użyć biblioteki SFML , która jest prostą i szybką biblioteką multimedialną. Zawiera wiele użytecznych i dobrze zdefiniowanych klas, takich jak Zegar, Gniazdo, Dźwięk, Grafika itp. Jest tak łatwy w użyciu i wysoce zalecany.
To jest przykład tego pytania.
źródło