Максимальное разрешение high_resolution_clock — 1000 нс

Я работаю с алгоритмами бенчмаркинга.
Я читаю о новом <chrono> заголовок в C ++ 11, так что я пошел с этим.

Я могу сделать измерения и все, но я борюсь с разрешением.

Когда делаешь что-то вроде

auto duration = chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count();

Я последовательно получаю времена, кратные 1000!

После дальнейшего расследования и выполнения следующих действий

cout << (double) chrono::high_resolution_clock::period::num /
chrono::high_resolution_clock::period::den << endl;

Я получил значение 1e-06 что микросекунды, не наносекунд. Он отлично отбрасывает до наносекунд, но бесполезно, если период с часов начинается только в микросекундах.

Я педантичен? Я знаю, что могу запустить свой тестовый код несколько раз и получить достаточно большое среднее время работы, и это то, что я делаю. Но для меня это почти принципиальный вопрос.

Дополнительная информация:
Я использую последнюю версию GCC (4.6.3) на сервере Ubuntu 12.04 X64 (я думаю)

0

Решение

Точность часов зависит от оборудования и операционной системы, на платформе x86 микросекунды Linux работают нормально. На моей красной шляпе 6 с ядром 2.6.30 я могу получить только около 10 мкс.

Чтобы получить лучшее разрешение, вам понадобится операционная система реального времени.

2

Другие решения

Fwiw, для меня это:

#include <ratio>
#include <chrono>
#include <string>

template <class Ratio, class CharT>
struct ratio_string
{
static std::basic_string<CharT> symbol()
{
return std::basic_string<CharT>(1, CharT('[')) +
std::to_string(Ratio::num) + CharT('/') +
std::to_string(Ratio::den) + CharT(']');
}
};

template <class CharT>
struct ratio_string<std::nano, CharT>
{
static std::basic_string<CharT> symbol()
{
return std::basic_string<CharT>(1, CharT('n'));
}
};

template <>
struct ratio_string<std::micro, char>
{
static std::string symbol() {return std::string("\xC2\xB5");}
};

template <>
struct ratio_string<std::micro, char16_t>
{
static std::u16string symbol() {return std::u16string(1, u'\xB5');}
};

template <>
struct ratio_string<std::micro, char32_t>
{
static std::u32string symbol() {return std::u32string(1, U'\xB5');}
};

template <>
struct ratio_string<std::micro, wchar_t>
{
static std::wstring symbol() {return std::wstring(1, L'\xB5');}
};

template <class CharT, class Rep, class Period>
inline
std::basic_string<CharT>
get_unit(const std::chrono::duration<Rep, Period>& d)
{
return ratio_string<Period, CharT>::symbol() + 's';
}

template <class Rep, class Period>
std::string
to_string(const std::chrono::duration<Rep, Period>& d)
{
return std::to_string(d.count()) + get_unit<char>(d);
}

#include <iostream>

int
main()
{
auto t0 = std::chrono::high_resolution_clock::now();
auto t1 = std::chrono::high_resolution_clock::now();
std::cout << to_string(t1-t0) << '\n';
}

при компиляции с -O3 выводит:

$ a.out
112ns
$ a.out
95ns
$ a.out
112ns
$ a.out
111ns

YMMV. Ваш вывод может быть аккуратнее, если вы добавите ratio_string специализаций.

3

У меня сложилось впечатление, что duration_cast на самом деле даст мне наносекунды, а не только то, что разработчик конкретной реализации решил сделать, как в случае с MSVC ++.

Нет, duration_cast просто преобразует длительность как есть в другой тип. Это не изменит то, как часы работают внутри, и не изменит разрешение часов.

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

auto duration = end_time - start_time;

И с chrono_io Говарда Хиннанта вы можете просто распечатать это напрямую, и это даст вам правильные единицы.

std::cout << duration << '\n';

Это распечатало бы что-то вроде 112ns, 2usи т. д. в зависимости от фактического разрешения.

0
По вопросам рекламы [email protected]