Jak uzyskać czas trwania, jako int milli i sekund zmiennoprzecinkowych z <chrono>?

94

Próbuję użyć biblioteki chronograficznej dla timerów i czasów trwania.

Chcę móc mieć Duration frameStart;(od początku aplikacji) i Duration frameDelta;(czas między klatkami)

Muszę mieć frameDeltaczas trwania w milisekundach i sekundach zmiennoprzecinkowych.

Jak to zrobić z nowymi <chrono>bibliotekami C ++ 11 ? Pracowałem nad tym i googlowałem (informacje są skąpe). Kod jest mocno szablonowy i wymaga specjalnych rzutów i innych rzeczy, nie mogę dowiedzieć się, jak poprawnie korzystać z tej biblioteki.

EddieV223
źródło
Przypisz czas trwania do czasu trwania ze stosunkiem sekund (lub milisekund), a następnie wywołaj countgo ...
K-ballo
auto delta = duration_cast <seconds> (frameDelta) .count (); Lubię to? Wraca długo, długo nie jest pływakiem.
EddieV223
3
@ K-ballo, jeśli czas trwania ma wyższą rozdzielczość niż typ, do którego go przypisałeś, przypisanie będzie źle sformułowane, aby uniknąć utraty precyzji. Musisz użyć czasu trwania z reprezentacją zmiennoprzecinkową lub użyćduration_cast
Jonathan Wakely
@JonathanWakely: Och, więc źle go używałem! :(
K-ballo

Odpowiedzi:

153

Czy tego szukasz?

#include <chrono>
#include <iostream>

int main()
{
    typedef std::chrono::high_resolution_clock Time;
    typedef std::chrono::milliseconds ms;
    typedef std::chrono::duration<float> fsec;
    auto t0 = Time::now();
    auto t1 = Time::now();
    fsec fs = t1 - t0;
    ms d = std::chrono::duration_cast<ms>(fs);
    std::cout << fs.count() << "s\n";
    std::cout << d.count() << "ms\n";
}

który dla mnie drukuje:

6.5e-08s
0ms
Howard Hinnant
źródło
2
dlaczego nie używać autona fsi d?
TemplateRex,
27
@rhalbersma: użycie autobyłoby w porządku d, ponieważ wynik duration_cast<ms>is ms. Jednak for fs autonie byłoby odpowiednie, ponieważ wynik funkcji t1-t0has type high_resolution_clock::durationniekoniecznie jest tego samego typu co duration<float>. Na przykład w moim systemie jest to duration<long long, nano>. W tym wierszu zachodzi więc niejawna konwersja z opartej nanosecondsna całkach na zmiennoprzecinkową seconds, tylko dlatego, że typ docelowy jest określony za pomocą fsec.
Howard Hinnant
2
To przydatne informacje. Po prostu ciekawy: czy auto fs = std::chrono::duration_cast<fsec>(t1 - t0);byłaby pedantyczna przesada?
TemplateRex,
@rhalbersma: To by działało równie dobrze i zrobiło dokładnie to samo. To, co powinno być preferowane, jest całkowicie stylistyczne, jeśli o mnie chodzi.
Howard Hinnant
2
pamiętaj, że w niektórych rzeczywistych scenariuszach (na przykład kompilator ms i biblioteki) 'high_resolution_clock' pominie czasy rzędu mikrosekund, a ten kod
wypluje
19

Zgadnij, o co prosisz. Zakładam, że według licznika czasu w milisekundach szukasz czegoś, co działa tak, jak poniżej,

double mticks()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (double) tv.tv_usec / 1000 + tv.tv_sec * 1000;
}

ale std::chronozamiast tego używa

double mticks()
{
    typedef std::chrono::high_resolution_clock clock;
    typedef std::chrono::duration<float, std::milli> duration;

    static clock::time_point start = clock::now();
    duration elapsed = clock::now() - start;
    return elapsed.count();
}

Mam nadzieję że to pomoże.

Billy dzieciak
źródło
Witamy w Stack Overflow. Byłoby wspaniale, gdybyś mógł podać dodatkowe szczegóły do ​​swojego kodu. Pomogłoby to innym ludziom zrozumieć, co próbujesz osiągnąć i jak działają Twoje rozwiązania. Dzięki!
Luís Cruz
FYI - to był NAJLEPSZY, najbardziej przydatny przykład z kilkudziesięciu, które sprawdziłem. Dzięki za uczynienie wiecznie mylących funkcji chronografu zrozumiałymi.
SMGreenfield
15

Nie wiem, co oznacza „milisekundy i zmienne sekundy”, ale to powinno dać ci wyobrażenie:

#include <chrono>
#include <thread>
#include <iostream>

int main()
{
  auto then = std::chrono::system_clock::now();
  std::this_thread::sleep_for(std::chrono::seconds(1));
  auto now = std::chrono::system_clock::now();
  auto dur = now - then;
  typedef std::chrono::duration<float> float_seconds;
  auto secs = std::chrono::duration_cast<float_seconds>(dur);
  std::cout << secs.count() << '\n';
}
Jonathan Wakely
źródło
Myślę, że chce rzeczywistego countjako float?
K-ballo
1
To jest drukowane na końcu. Ale nie wiedziałem, czy chce milisekund jako liczby całkowitej, czy milisekund po drugiej, czy co.
Jonathan Wakely
Chciałbym móc uzyskać z chrono :: duration czas trwania reprezentowany jako int milisekundy lub zmiennoprzecinkowe sekundy (ułamek sekundy)
EddieV223
Odpowiedź Howarda właśnie to robi
Jonathan Wakely
8

W stylu AAA przy użyciu jawnie wpisanego idiomu inicjatora :

#include <chrono>
#include <iostream>

int main(){
  auto start = std::chrono::high_resolution_clock::now();
  // Code to time here...
  auto end = std::chrono::high_resolution_clock::now();

  auto dur = end - start;
  auto i_millis = std::chrono::duration_cast<std::chrono::milliseconds>(dur);
  auto f_secs = std::chrono::duration_cast<std::chrono::duration<float>>(dur);
  std::cout << i_millis.count() << '\n';
  std::cout << f_secs.count() << '\n';
}
Chris Drew
źródło