Подтвердить что ты не робот

Разрешение std:: chrono:: high_resolution_clock не соответствует измерениям

Позвольте мне задать свой вопрос в этой тестовой программе:

#include <iostream>
#include <chrono>

using std::chrono::nanoseconds;
using std::chrono::duration_cast;

int main(int argc, char* argv[])
{
    std::cout << "resolution (nano) = " << (double) std::chrono::high_resolution_clock::period::num
        / std::chrono::high_resolution_clock::period::den * 1000 * 1000 * 1000 << std::endl;

    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << "how much nanoseconds std::cout takes?" << std::endl;
    auto t2 = std::chrono::high_resolution_clock::now();


    auto diff = t2-t1;
    nanoseconds ns = duration_cast<nanoseconds>(diff);

    std::cout << "std::cout takes " << ns.count() << " nanoseconds" << std::endl;
    return 0;
}

Выход на моей машине:

разрешение (nano) = 100

сколько наносекунд std:: cout принимает?

std:: cout принимает 1000200 наносекунд

В результате я получаю либо 1000200, либо 1000300 или 1000400 или 1000500 или 1000600 или 2000600 (= 1 или 2 микросекунды). Очевидно, что либо разрешение std::chrono не 100 наносекунд , либо, поскольку я измеряю время std::cout неправильно. (почему я никогда не получаю что-то между 1 и 2 микросекундами, например 1500000?)

Мне нужен таймер с высоким разрешением в С++. Сама ОС обеспечивает таймер с высоким разрешением, потому что я могу измерять вещи с точностью до микросекунды, используя класс С# Stopwatch на той же машине. Поэтому мне просто нужно правильно использовать таймер высокого разрешения, который имеет ОС!

Как исправить мою программу для получения ожидаемых результатов?

4b9b3361

Ответ 1

Я собираюсь предположить, что вы используете VS2012; Если нет, не принимайте во внимание этот ответ. VS2012 typedef high_resolution_clock до system_clock. К сожалению, это означает, что у него дерьмовая точность (около 1 мс). Я написал лучшие часы с высоким разрешением, которые используют QueryPerformanceCounter для использования в VS2012...

HighResClock.h:

    struct HighResClock
    {
        typedef long long                               rep;
        typedef std::nano                               period;
        typedef std::chrono::duration<rep, period>      duration;
        typedef std::chrono::time_point<HighResClock>   time_point;
        static const bool is_steady = true;

        static time_point now();
    };

HighResClock.cpp:

namespace
{
    const long long g_Frequency = []() -> long long 
    {
        LARGE_INTEGER frequency;
        QueryPerformanceFrequency(&frequency);
        return frequency.QuadPart;
    }();
}

HighResClock::time_point HighResClock::now()
{
    LARGE_INTEGER count;
    QueryPerformanceCounter(&count);
    return time_point(duration(count.QuadPart * static_cast<rep>(period::den) / g_Frequency));
}

(Я упустил assert и #ifs, чтобы посмотреть, компилируется ли он в 2012 году из приведенного выше кода)

Вы можете использовать эти часы везде и так же, как стандартные часы.

Ответ 2

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


Низкое разрешение Visual Studio high_resolution_clock было проблемой в течение нескольких лет. Стандартная библиотека Microsoft С++, Stephan T. Lavavej, указала, что это было исправлено в VS2015 с помощью QueryPerformanceCounter().

Ответ 3

Может быть, реализация не реализует таймер с более высоким разрешением?

Кажется, вы используете Windows (вы упоминаете С#), поэтому, если вы используете таймер, и вы действительно используете окна, вы можете использовать QueryPerformanceFrequency и QueryPerformanceCounter.