ミリ秒レベルまでの詳細なタイミング情報を必要とする C++ アプリケーションに取り組んでいます。
time()
の標準関数を使用して、秒精度までの時間を収集する予定<ctime>
です。で与えられた最後の秒から経過したミリ秒をさらに収集したいと思いtime()
ます。
この情報を取得するための便利な方法を知っている人はいますか?
ミリ秒レベルまでの詳細なタイミング情報を必要とする C++ アプリケーションに取り組んでいます。
time()
の標準関数を使用して、秒精度までの時間を収集する予定<ctime>
です。で与えられた最後の秒から経過したミリ秒をさらに収集したいと思いtime()
ます。
この情報を取得するための便利な方法を知っている人はいますか?
Boost.DateTime には、基盤となるプラットフォームがサポートしている場合、ミリ秒とナノ秒の表現があります。プラットフォーム固有のコードを使用している間、それらの詳細をコードから除外しています。
それが大したことである場合、プラットフォームに依存しないサブ秒の解決を行う別の方法があります。 このページの数段落下では、その方法について説明しています。
(ページより)
たとえば、10 分の 1 秒を表すカウントを使用して構築したいとします。つまり、各ティックは 0.1 秒です。
int number_of_tenths = 5;
//create a resolution independent count -- divide by 10 since there are
//10 tenths in a second.
int count = number_of_tenths*(time_duration::ticks_per_second()/10);
time_duration td(1,2,3,count); //01:02:03.5 //no matter the resolution settings
ANSI C では標準のミリ秒精度の時間関数が定義されていないため、この問題に対する移植可能な解決策はありません。Windows を使用している場合は、GetTickCount()、timeGetTime()、または QueryPerformanceCounter()/QueryPerformanceFrequency() を使用できます。これらは異なる精度と異なるランタイム コストを持つことに注意してください。
他のオペレーティング システムにも同様の機能があります。彼らが私の頭の上から何をしているのかわかりません。
Windows の GetTickCount gettimeofday in *nix QueryPerformanceCounter for Windows
他の人が言ったように、これを行うための移植可能な方法はありません。
私が (msvc++ および linux/g++ で) 行うことは、Windows で QueryPerformanceCounter を使用し、Linux で gettimeofday を使用する次のクラスを使用することです。2 つの呼び出し間の経過時間を取得できるタイマー クラスです。ニーズに合わせて変更することもできます。
#if defined(_MSC_VER)
# define NOMINMAX // workaround un bug dans windows.h qui define des macros
// "min" et "max" qui entrent en conflit avec la STL.
# include <windows.h>
#else
# include <sys/time.h>
#endif
namespace Utils
{
/**
* Implémente un chronométre qui mesure le temps etre deux appels.
*/
class CTimer
{
private:
# if defined(_MSC_VER)
LARGE_INTEGER m_depart;
# else
timeval m_depart;
# endif
public:
/**
* Démarre le timer.
*
* Cette fonction sert à démarrer le timer. Si le timer est déja
* démarrer, elle le redémarre simplement.
*/
inline void start()
{
# if defined(_MSC_VER)
QueryPerformanceCounter(&m_depart);
# else
gettimeofday(&m_depart, 0);
# endif
};
/**
* Retourne le nombre de secondes depuis le départ du timer.
*
* @return Nombre de secondes écoulés depuis le départ du timer
*/
inline float GetSecondes() const
{
# if defined(_MSC_VER)
LARGE_INTEGER now;
LARGE_INTEGER freq;
QueryPerformanceCounter(&now);
QueryPerformanceFrequency(&freq);
return (now.QuadPart - m_depart.QuadPart) / static_cast<float>(freq.QuadPart);
# else
timeval now;
gettimeofday(&now, 0);
return now.tv_sec - m_depart.tv_sec + (now.tv_usec - m_depart.tv_usec) / 1000000.0f;
# endif
};
};
}
Unix を使用している場合、gettimeofday()はシステム クロックの分解能までの秒とマイクロ秒を返します。
int gettimeofday(struct timeval *tv, struct timezone *tz);
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
Intel プロセッサー向けの高解像度、低オーバーヘッドのタイミング
Intel ハードウェアを使用している場合、CPU リアルタイム命令カウンターを読み取る方法は次のとおりです。プロセッサが起動してから実行された CPU サイクルの数がわかります。これはおそらく、パフォーマンス測定用に取得できる最も細かいカウンターです。
これは CPU サイクルの数であることに注意してください。Linux では、/proc/cpuinfo から CPU 速度を取得し、除算して秒数を取得できます。これを double に変換すると非常に便利です。
これを自分のボックスで実行すると、
11867927879484732 11867927879692217 printf を呼び出すのにこれほど時間がかかりました: 207485
これは、大量の詳細を提供するIntel 開発者ガイドです。
#include < stdio.h > // stackoverflow bug: pre tag eats the filenames,
#include < stdint.h > // so i had to put spaces in the angle brackets
inline uint64_t rdtsc() {
uint32_t lo, hi;
__asm__ __volatile__ (
"xorl %%eax, %%eax\n"
"cpuid\n"
"rdtsc\n"
: "=a" (lo), "=d" (hi)
:
: "%ebx", "%ecx");
return (uint64_t)hi << 32 | lo;
}
main()
{
unsigned long long x;
unsigned long long y;
x = rdtsc();
printf("%lld\n",x);
y = rdtsc();
printf("%lld\n",y);
printf("it took this long to call printf: %lld\n",y-x);
}
#include <ctime>
clock_t elapsed = static_cast<double>(clock() / CLOCKS_PER_SEC);
経過は、経過したプロセッサ時間(秒単位)になります。
解像度はオペレーティングシステムに依存しますが、ほとんどのシステムでは一般的にミリ秒の解像度よりも優れています。
ヘッダーにないものには、(c)time.h
OS 固有のメソッドが必要です。これらの方法はすべて二次解決だと思います。
どのOSで作業していますか?
これが Windows の場合は、QueryPerformanceCounter メソッドを調べてください。
Intel のThreading Building Blocks ライブラリにはこの機能がありますが、TBB は現在 Intel とクローンでのみ利用できます (つまり、SPARC、PowerPC、ARM などでは利用できません)。