MSVC++2012 の std::chrono
下にあるクラスの時間精度は、良くてミリ秒オーダだと思ったほうが良い
- まとめ:
std::chrono
下の全クラスは時刻取得に_Xtime_get_ticks()
を用いている
%ProgramFiles(x86)\Microsoft Visual Studio 11.0\VC\include\chrono
内での定義は以下のようになっている
// MSVC++2012 : <chrono>
namespace std {
namespace chrono {
struct system_clock {
...
static time_point now() __NOEXCEPT {
return (time_point(duration(_Xtime_get_ticks())));
}
...
};
class steady_clock : public system_clock { ... };
typedef steady_clock monotonic_clock;
typedef system_clock high_resolution_clock;
}
}
つまり std::chrono
下のクラス
system_clock
, steady_clock
, monotonic_clock
, high_resolution_clock
は
時刻取得(now())に _Xtime_get_ticks()
を用いており、精度の違いは無い。
- まとめ :
_Xtime_get_ticks()
は WIN32 APIGetSystemTimeAsFileTime()
を用いて時刻を取得している
%ProgramFiles(x86)\Microsoft Visual Studio 11.0\VC\crt\src\thr\xtime.c
によると、
以下のようになっている
_LONGLONG _Xtime_get_ticks() {
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
... 以下 ft を適宜変換する ...
}
つまり WIN32 API GetSystemTimeAsFileTime()
によって精度が決まる。
この API の返す値は単純にシステム(ドライバ)依存なので、 以下のようなコードで簡単に実測した
#include <windows.h>
#include <stdint.h>
#include <array>
#include <chrono>
static uint64_t getTime() {
ULARGE_INTEGER uli;
GetSystemTimeAsFileTime((LPFILETIME) &uli);
return uli.QuadPart;
}
int main() {
typedef std::chrono::steady_clock Clk;
static std::array<uint64_t, 1000 * 1000 * 10> a = { 0 };
uint64_t t0 = getTime();
for(auto e = Clk::now() + std::chrono::seconds(5); Clk::now() < e; ) {
uint64_t t1 = getTime();
a[(size_t) min(t1-t0, a.size()-1)] += 1;
t0 = t1;
}
for(size_t i = 0; i < a.size(); ++i) {
a[i] && printf("%9d nsec : %10lld\n", i * 100, a[i]);
}
return 0;
}
# 別のタイマ源を用いて、実時間としての精度も見るべきだけど、面倒なのでしていない
手元の環境 (ASUS P8Z68-V, Core i7-2600K 3.40GHz, Windows7 x64) では以下のようになった:
0 nsec : 379730723
1000000 nsec : 2139
1000100 nsec : 2860
つまり、ほぼ1ミリ秒 (100万ナノ秒) の精度で値を返している。
- MSVC++2012 の
std::chrono
下の全クラスは、WIN32 APIGetSystemTimeAsFileTime()
によって時刻を取得している - この API の数値表現上の精度は、100 ナノ秒単位となっている
- ただし、実際の時間精度は環境依存となる
- 手元で実測した限りでは、1 ミリ秒程度だった
- ネット上で検索したところでは、2012 年時点でのこの API の精度は KHz (ミリ秒) オーダのようだ
- wine 環境だと gettimeofday() で実装されているので、高精度になる
- よって MSVC++2012 の
std::chrono
には、2012 年時点でのQueryPerformanceCounter()
に期待される MHz (マイクロ秒) オーダの精度は見込めない
VC++2019かつWindows8以降の場合、下記のように実装されている。計測した限り、
system_clock
,steady_clock
のいずれの場合も、実計測時間で100ns精度の値が返ってくる。また、steady_clock::now()
のほうが若干処理時間が短いように見える。1フレに数十回程度の実行であれば、気にする必要はないかも。