¿Cómo obtener la duración, como int milli's y float segundos de <chrono>?

94

Estoy intentando usar la biblioteca de crono para temporizadores y duraciones.

Quiero poder tener un Duration frameStart;(desde el inicio de la aplicación) y un Duration frameDelta;(tiempo entre cuadros)

Necesito poder obtener la frameDeltaduración en milisegundos y segundos flotantes.

¿Cómo se hace esto con las nuevas <chrono>bibliotecas de c ++ 11 ? He estado trabajando en ello y buscando en Google (la información es escasa). El código tiene muchas plantillas y requiere moldes especiales y cosas, no puedo entender cómo usar esta biblioteca correctamente.

EddieV223
fuente
Asigne la duración a una duración con una proporción de segundos (o milisegundos) y luego invoque count...
K-Ballo
auto delta = duration_cast <seconds> (frameDelta) .count (); ¿Me gusta esto? Vuelve mucho tiempo sin flotar.
EddieV223
3
@ K-Ballo, si la duración tiene una resolución más alta que el tipo que le asignó, entonces la asignación estará mal formada, para evitar perder precisión. Debe usar una duración con una representación de punto flotante, o useduration_cast
Jonathan Wakely
@JonathanWakely: ¡Oh, entonces lo he estado usando mal! :(
K-Ballo

Respuestas:

154

¿Es esto lo que estás buscando?

#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";
}

que para mí imprime:

6.5e-08s
0ms
Howard Hinnant
fuente
2
¿por qué no usar autoen fsy d?
TemplateRex
27
@rhalbersma: El uso de autoestaría bien para d, como resultado de duration_cast<ms>is ms. Sin embargo, para fs autono sería apropiado porque el resultado de t1-t0tiene un tipo high_resolution_clock::durationque no es necesariamente del mismo tipo que duration<float>. Por ejemplo, en mi sistema lo es duration<long long, nano>. Entonces, hay una conversión implícita de basado nanosecondsen integral a basado en flotante secondsen esa línea, solo porque el tipo de destino se especifica con fsec.
Howard Hinnant
2
Esa es información útil. Solo por curiosidad: ¿sería auto fs = std::chrono::duration_cast<fsec>(t1 - t0);una exageración pedante?
TemplateRex
@rhalbersma: Eso funcionaría igual de bien y haría exactamente lo mismo. En cuanto a cuál se debe preferir, es completamente estilístico en lo que a mí respecta.
Howard Hinnant
2
tenga en cuenta que en algunos escenarios del mundo real (el compilador ms y las bibliotecas, por ejemplo) el 'high_resolution_clock' perderá tiempos del orden de microsegundos y este código arrojará ceros,
jheriko
19

Adivinando qué es lo que estás pidiendo. Supongo que, por un temporizador de fotogramas de milisegundos, está buscando algo que actúe como lo siguiente,

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

pero usa en su std::chronolugar,

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();
}

Espero que esto ayude.

Billy el niño
fuente
Bienvenido a Stack Overflow. Sería genial si pudiera proporcionar detalles adicionales a su código. Ayudaría a otras personas a comprender lo que está tratando de lograr y cómo funcionan sus soluciones. ¡Gracias!
Luís Cruz
FYI: este fue el ejemplo MÁS CLARO y útil de las docenas que revisé. Gracias por hacer comprensibles las eternamente confusas funciones del cronógrafo.
SMGreenfield
15

No sé qué significa "milisegundos y segundos flotantes", pero esto debería darte una idea:

#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
fuente
Supongo que quiere lo real countcomo un float?
K-Ballo
1
Eso es lo que se imprime al final. Pero no sabía si quiere milisegundos como un número entero, o milisegundos después del segundo, o qué.
Jonathan Wakely
Me gustaría poder obtener de un chrono :: duration la duración representada como milisegundos int, o segundos flotantes (fracción de segundo)
EddieV223
La respuesta de Howard hace exactamente eso
Jonathan Wakely
8

En estilo AAA usando el idioma inicializador escrito explícitamente :

#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
fuente