Несколько вопросов о заголовке <chrono> в С++ 11

У меня есть несколько вопросов о новом заголовке <chrono> в С++ 11. Использование Windows 7, Visual Studio 2012.

Посмотрите на пример http://en.cppreference.com/w/cpp/chrono

#include <iostream>
#include <chrono>
#include <ctime>

int fibonacci(int n)
{
    if (n < 3) return 1;
    return fibonacci(n-1) + fibonacci(n-2);
}

int main()
{
    std::chrono::time_point<std::chrono::system_clock> start, end;
    start = std::chrono::system_clock::now();
    int result = fibonacci(42);
    end = std::chrono::system_clock::now();

    int elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>
                             (end-start).count();
    std::time_t end_time = std::chrono::system_clock::to_time_t(end);

    std::cout << "finished computation at " << std::ctime(&end_time)
              << "elapsed time: " << elapsed_seconds << "s\n";
}

Возможный выход

finished computation at Sat Jun 16 20:42:57 2012
elapsed time: 3s
  • Я заметил, что в примере используется std::chrono::system_clock::now(); означает ли это, что он может использоваться для измерения только прошедшего времени, а не времени процессора? И если я хочу измерить время процессора, какие часы я должен использовать?
  • Обратите внимание, что вывод elapsed time: 3s округляется до целого целого. Есть ли способ сделать его более гранулированным?

Ответ 1

  • Correct

    В соответствии со стандартом:

    system_clock представляет [s] время настенных часов из общесистемных часов реального времени.

    Библиотека <chrono> не предоставляет механизм для измерения времени процессора, поэтому, если вы хотите, чтобы вам пришлось вернуться к старой библиотеке <ctime> и использовать std::clock().

    (И если вы ориентируетесь на Windows, вам придется отказаться от того, какой API-интерфейс, определенный платформой, обеспечивает получение процессорного времени, поскольку, как вы отмечаете, их std::clock() работает неправильно.)

    system_clock больше похож на std::time(), чем на std::clock(). (Например, обратите внимание, что system_clock обеспечивает конверсии между system_clock::time_point и time_t.) Я полагаю, что отсутствие часов в <chrono> для измерения времени процессора обусловлено временными ограничениями для стандартного комитета и тем фактом, что это функциональность менее используется, чем системные настенные часы и часы реального времени.

    Если вы хотите процессорное время, но также хотите преимущества, предоставляемые <chrono>, вам следует реализовать тип часов, который соответствует концепции часов, изложенной в стандарте, и которая обеспечивает время процессора, возможно, внутренне используя std::clock().

  • Строка, в которой говорится

    int elapsed_seconds = std::chrono::duration_cast<std::chrono::seconds>
                        (end-start).count();
    

    - это то, что заставляет время округлить до целого числа секунд. Вы можете выбрать любой период, который вам бы хотелось, или вы можете использовать представление с плавающей запятой, чтобы позволить нецелые значения:

    std::int64_t elapsed_attoseconds =
        std::chrono::duration_cast<std::chrono::duration<std::int64_t, std::atto>>
            (end-start).count();
    
    double elapsed_seconds =
        std::chrono::duration_cast<std::chrono::duration<double,std::ratio<1>>>
            (end-start).count();
    

    Обратите внимание, что в реальном коде вам следует избегать использования .count(), чтобы избежать сильного ввода, предоставленного chrono::duration, пока вы не обязательно будете.

    auto total_duration = end - start;
    auto seconds = std::chrono::duration_cast<std::chrono::seconds>(total_duration);
    auto milli = std::chrono::duration_cast<std::chrono::milliseconds>(total_duration - seconds);
    
    std::cout << seconds.count() << "s " << milli.count() << "ms\n";
    

Ответ 2

1) Я уверен, что самое высокое разрешение, которое вы можете получить, это использовать std::chrono::high_resolution_clock, а затем не выполнять кастинг продолжительностью:

int elapsed_ticks = (end-start).count();

2) Измените аргумент duration_cast на что-то вроде nanoseconds:

int elapsed_seconds = std::chrono::duration_cast<std::chrono::nanoseconds>
                             (end-start).count();