Como obter a duração, como int milli's e segundos flutuantes de <crono>?

93

Estou tentando usar a biblioteca chrono para cronômetros e durações.

Eu quero ser capaz de ter um Duration frameStart;(desde o início do aplicativo) e um Duration frameDelta;(tempo entre os quadros)

Preciso ser capaz de obter a frameDeltaduração em milissegundos e segundos flutuantes.

Como você faz isso com as novas <chrono>bibliotecas c ++ 11 ? Estive trabalhando nisso e pesquisando no Google (as informações são esparsas). O código é fortemente modelado e requer casts e coisas especiais, não consigo descobrir como usar essa biblioteca corretamente.

EddieV223
fonte
Atribua a duração a uma duração com razão de segundos (ou milissegundos) e então solicite count...
K-ballo
delta automático = duração_cast <segundos> (frameDelta) .count (); Como isso? Ele retorna muito tempo, não um flutuador.
EddieV223
3
@ K-ballo, se a duração tiver uma resolução mais alta do que o tipo que você atribuiu, a atribuição será malformada, para evitar perda de precisão. Você precisa usar uma duração com uma representação de ponto flutuante ou usarduration_cast
Jonathan Wakely
@JonathanWakely: Oh, então estou usando errado! :(
K-ballo

Respostas:

151

É isso que você está procurando?

#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 mim imprime:

6.5e-08s
0ms
Howard Hinnant
fonte
2
por que não usar autoem fse d?
TemplateRex
26
@rhalbersma: O uso de autoseria adequado para d, como resultado do duration_cast<ms>is ms. No entanto, para fs autonão seria apropriado porque o resultado de t1-t0tem um tipo high_resolution_clock::durationque não é necessariamente o mesmo tipo que duration<float>. Por exemplo, no meu sistema é duration<long long, nano>. Portanto, há uma conversão implícita de baseado nanosecondsem integral para baseado em flutuante secondsacontecendo nessa linha, apenas porque o tipo de destino é especificado com fsec.
Howard Hinnant
2
Essa é uma informação útil. Só por curiosidade: seria auto fs = std::chrono::duration_cast<fsec>(t1 - t0);um exagero pedante?
TemplateRex
@rhalbersma: Isso também funcionaria e faria exatamente a mesma coisa. Quanto a qual deve ser preferido é inteiramente estilístico, tanto quanto eu estou preocupado.
Howard Hinnant
2
esteja ciente de que em alguns cenários do mundo real (o compilador ms e bibliotecas, por exemplo) o 'high_resolution_clock' perderá tempos da ordem de microssegundos e este código cuspirá zeros,
jheriko
19

Adivinhar o que você está pedindo. Estou supondo que por temporizador de quadro de milissegundos você está procurando algo que funcione como o seguinte,

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

mas usa em std::chronovez disso,

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 isto ajude.

Billy the Kid
fonte
Bem-vindo ao Stack Overflow. Seria ótimo se você pudesse fornecer detalhes adicionais ao seu código. Isso ajudaria outras pessoas a entender o que você está tentando realizar e como suas soluções funcionam. Obrigado!
Luís Cruz
Para sua informação - este foi o exemplo MAIS CLARO e mais útil das dezenas que analisei. Obrigado por tornar compreensíveis as funções crono eternamente confusas.
SMGreenfield
15

Não sei o que significa "milissegundos e segundos flutuantes", mas isso deve dar uma ideia:

#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
fonte
Eu acho que ele quer o real countcomo um float?
K-ballo
1
Isso é o que é impresso no final. Mas eu não sabia se ele queria milissegundos como um número inteiro, ou milissegundos depois do segundo, ou o quê.
Jonathan Wakely
Eu gostaria de ser capaz de obter de um crono :: duração a duração representada como milissegundos
inteiros
A resposta de Howard faz exatamente isso
Jonathan Wakely
8

No estilo AAA usando o idioma inicializador explicitamente digitado :

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