简体   繁体   中英

high_resolution_clock's highest resolution is 1000ns

I'm doing work involving benchmarking algorithms. I read about the new <chrono> header in C++11, so I went with that.

I can take measurements and everything, but I am struggling with resolution.

When doing something like

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

I consistently get times that are multiples of 1000!

Upon investigating further and doing the following

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

I got a value of 1e-06 which is microseconds, not nanoseconds. It casts to nanoseconds fine, but it's useless if if the period of the clock is only in microseconds to start with.

Am I being pedantic? I know I can run my test code multiple times and get a nice large average time to work with, and that is what I'm doing. But it's almost a matter of principle for me.

Extra Info: I use the latest version of GCC (4.6.3) on Ubuntu 12.04 server X64 (I think)

Fwiw, for me, this:

#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';
}

when compiled with -O3, outputs:

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

YMMV. Your output may be neater if you add ratio_string specializations.

The precision of clock is hardware and operating system dependent, on x86 platform running linux microseconds is quite normal. On my red hat 6 with 2.6.30 kernel, I can only get about 10µs.

To get better resolution, you'll need a real time operating system.

I was just under impression that duration_cast would actually give me nanoseconds and not just whatever that specific implementation's maintainer decided to do as in MSVC++'s case.

No, duration_cast will simply convert the duration as-is to another type. It will not change how the clock operates internally or change the clock's resolution.

In general it's a good idea not to do these casts or conversions, and instead just allow the implementation to pick the appropriate type. It's also simpler this way:

auto duration = end_time - start_time;

And with Howard Hinnant's chrono_io you can just print this out directly and it will give you the right units.

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

That would print out something like 112ns , 2us , etc. depending on the actual resolution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM