high_resolution_clock的最高分辨率为1000ns

high_resolution_clock's highest resolution is 1000ns

本文关键字:高分辨率 1000ns resolution clock high      更新时间:2023-10-16

我正在做涉及基准算法的工作。我读到c++ 11中新的<chrono>头文件,所以我就这么做了。

我可以测量和做任何事情,但我在分辨率上挣扎。

当做类似

的事情时
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的值,它是微秒,不是纳秒。它可以强制转换为纳秒,但如果时钟周期开始时只有微秒,那么它就没有用了。

我是不是太迂腐了?我知道我可以多次运行我的测试代码,并得到一个相当大的平均工作时间,这就是我正在做的。但对我来说,这几乎是一个原则问题。

额外信息:我在Ubuntu 12.04服务器X64上使用最新版本的GCC(4.6.3)(我想)

对我来说,这是:

#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("xC2xB5");}
};
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专门化,您的输出可能会更整洁。

时钟的精度取决于硬件和操作系统,在x86平台上运行linux微秒是很正常的。在我的红帽6和2.6.30内核上,我只能得到大约10µs。

要获得更好的分辨率,您需要一个实时操作系统。

在我的印象中,duration_cast实际上会给我毫微秒,而不仅仅是特定实现的维护者决定做的事情,就像msvc++的情况一样。

不,duration_cast将简单地将持续时间转换为另一种类型。它不会改变时钟的内部运行方式,也不会改变时钟的分辨率。

一般来说,最好不要进行这些类型强制转换或转换,而只允许实现选择适当的类型。这样也更简单:

auto duration = end_time - start_time;

使用Howard Hinnant的chrono_io你可以直接打印出来它会给你正确的单位

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

会根据实际分辨率打印出112ns, 2us等。