Reputation: 272
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)
Upvotes: 0
Views: 584
Reputation: 219478
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.
Upvotes: 3
Reputation: 88225
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.
Upvotes: 0
Reputation: 5249
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.
Upvotes: 2