Windowsでは、clock()
は時間をミリ秒単位で返しますが、作業中のこのLinuxボックスでは、最も近い1000に丸められるため、精度はミリ秒レベルではなく「秒」レベルになります。
QTime
クラスを使用し、オブジェクトをインスタンス化してstart()
を呼び出し、次にelapsed()
を呼び出して経過したミリ秒数を取得するQtのソリューションを見つけました。
そもそもQtと一緒に仕事をしているので、ちょっとラッキーになりましたが、サードパーティのライブラリに依存しないソリューションが欲しいのですが、
これを行う標準的な方法はありませんか?
UPDATE
Boostを推奨しないでください..
BoostとQtができるなら、それは確かに魔法ではありません。彼らが使用している標準がなければなりません!
メソッドの開始時と終了時にgettimeofdayを使用して、2つの戻り構造体を区別できます。次のような構造が得られます。
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
}
#include <sys/time.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
struct timeval start, end;
long mtime, seconds, useconds;
gettimeofday(&start, NULL);
usleep(2000);
gettimeofday(&end, NULL);
seconds = end.tv_sec - start.tv_sec;
useconds = end.tv_usec - start.tv_usec;
mtime = ((seconds) * 1000 + useconds/1000.0) + 0.5;
printf("Elapsed time: %ld milliseconds\n", mtime);
return 0;
}
clock
はnot壁時計時間を測定することに注意してください。つまり、プログラムに5秒かかる場合、clock
は必ずしも5秒を測定しませんが、それより長くなる可能性があります(プログラムは複数のスレッドを実行できるため、リアルタイムよりも多くのCPUを消費する可能性があります)。 CPU時間の近似値を測定します。違いを確認するには、このコードを検討してください
#include <iostream>
#include <ctime>
#include <unistd.h>
int main() {
std::clock_t a = std::clock();
sleep(5); // sleep 5s
std::clock_t b = std::clock();
std::cout << "difference: " << (b - a) << std::endl;
return 0;
}
私のシステムに出力します
$ difference: 0
なぜなら、私たちがしたのはスリープ状態で、CPU時間をまったく使用しなかったからです!ただし、gettimeofday
を使用すると、必要なものが得られます(?)
#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/time.h>
int main() {
timeval a;
timeval b;
gettimeofday(&a, 0);
sleep(5); // sleep 5s
gettimeofday(&b, 0);
std::cout << "difference: " << (b.tv_sec - a.tv_sec) << std::endl;
return 0;
}
システム上の出力
$ difference: 5
もっと精度が必要なのにCPU時間を取得したい場合は、getrusage
関数の使用を検討できます。
Boostが提供するツールもお勧めします。前述のブーストタイマー、またはBoost.DateTimeから何かをハックするか、サンドボックスに新しい提案されたライブラリがあります- Boost.Chrono :この最後のものはタイマーの代替品であり、次の機能があります。
duration
time_point
system_clock
monotonic_clock
high_resolution_clock
timer
、typedefs:system_timer
monotonic_timer
high_resolution_timer
process_clock
、実時間、ユーザーCPU時間、およびシステムCPU時間をキャプチャします。process_timer
、経過した実時間、ユーザーCPU時間、およびシステムCPU時間をキャプチャします。run_timer
、| process_timer |の便利なレポート結果。機能リストのソース はこちら
CTT's answer に基づいてTimer
クラスを作成しました。次の方法で使用できます。
Timer timer = Timer();
timer.start();
/* perform task */
double duration = timer.stop();
timer.printTime(duration);
その実装は次のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
using namespace std;
class Timer {
private:
timeval startTime;
public:
void start(){
gettimeofday(&startTime, NULL);
}
double stop(){
timeval endTime;
long seconds, useconds;
double duration;
gettimeofday(&endTime, NULL);
seconds = endTime.tv_sec - startTime.tv_sec;
useconds = endTime.tv_usec - startTime.tv_usec;
duration = seconds + useconds/1000000.0;
return duration;
}
static void printTime(double duration){
printf("%5.6f seconds\n", duration);
}
};
古いユニックスにコードを移植する必要がない場合は、clock_gettime()を使用できます。これにより、時間をnanoseconds(プロセッサがその解像度をサポートしている場合)で取得できます。 POSIXですが、2001年からです。
clock()の解像度は非常に低くなります。ミリ秒レベルで時間を測定したい場合、この質問で説明されているように 、clock_gettime()を使用する方法があります。
(Linuxでは-lrtとリンクする必要があることに注意してください)。
C++ 11およびstd::chrono::high_resolution_clock
を使用すると、次のことができます。
#include <iostream>
#include <chrono>
#include <thread>
typedef std::chrono::high_resolution_clock Clock;
int main()
{
std::chrono::milliseconds three_milliseconds{3};
auto t1 = Clock::now();
std::this_thread::sleep_for(three_milliseconds);
auto t2 = Clock::now();
std::cout << "Delta t2-t1: "
<< std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count()
<< " milliseconds" << std::endl;
}
出力:
Delta t2-t1: 3 milliseconds
デモへのリンク: http://cpp.sh/2zdt
clock()は、Linuxではミリ秒または秒を返しません。通常、clock()は、Linuxシステムではマイクロ秒を返します。 clock()によって返された値を解釈する適切な方法は、CLOCKS_PER_SECで値を除算して、経過した時間を把握することです。
POSIX標準では、clock
の戻り値はCLOCKS_PER_SECシンボルで定義されており、実装では便利な方法でこれを自由に定義できます。 Linuxでは、times()
関数を使用して幸運に恵まれました。
gettimeofday-問題は、ハードウェアクロック(NTPなど)を変更すると、値が低くなる可能性があることです。その容量は小さく、しばらくすると負の数が返されます。
私は独自のクラスを作成して10ミリ秒ごとに更新することを好むので、この方法はより柔軟であり、サブスクライバーを持つように改善することさえできます。
class MyAlarm {
static int64_t tiempo;
static bool running;
public:
static int64_t getTime() {return tiempo;};
static void callback( int sig){
if(running){
tiempo+=10L;
}
}
static void run(){ running = true;}
};
int64_t MyAlarm::tiempo = 0L;
bool MyAlarm::running = false;
それを更新するには、setitimerを使用します。
int main(){
struct sigaction sa;
struct itimerval timer;
MyAlarm::run();
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &MyAlarm::callback;
sigaction (SIGALRM, &sa, NULL);
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 10000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 10000;
setitimer (ITIMER_REAL, &timer, NULL);
.....
SetitimerとITIMER_VIRTUALおよびITIMER_REALを見てください。
アラームまたはualarm機能を使用しないでください。プロセスが苦労すると精度が低下します。
これは動作するはずです... Macでテストしました...
#include <stdio.h>
#include <sys/time.h>
int main() {
struct timeval tv;
struct timezone tz;
struct tm *tm;
gettimeofday(&tv,&tz);
tm=localtime(&tv.tv_sec);
printf("StartTime: %d:%02d:%02d %d \n", tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec);
}
うん...それを2回実行して減算...
Gettimeofday()を使用しないHola Soyメソッドが好きです。実行中のサーバーで、管理者がタイムゾーンを変更しました。クロックは、同じ(正しい)ローカル値を表示するように更新されました。これにより、関数time()およびgettimeofday()が2時間シフトし、一部のサービスのすべてのタイムスタンプがスタックしました。
更新として、Windowsでclock()がウォールクロック時間を測定する(CLOCKS_PER_SEC精度で)
http://msdn.Microsoft.com/en-us/library/4e2ess30(VS.71).aspx
linuxでは、現在のプロセスで使用されるコア全体のCPU時間を測定します
http://www.manpagez.com/man/3/clock
そして、(それが表示され、元のポスターで述べられているように)実際にはless CLOCKS_PER_SECよりも精度が高いですが、これはおそらくLinuxの特定のバージョンに依存します。
Boost Timer library の方が簡単ですが、サードパーティのライブラリを使用したくない場合は、clock()を使用するのが妥当と思われます。
timeb
を使用してC++
クラスを作成しました。
#include <sys/timeb.h>
class msTimer
{
public:
msTimer();
void restart();
float elapsedMs();
private:
timeb t_start;
};
メンバー関数:
msTimer::msTimer()
{
restart();
}
void msTimer::restart()
{
ftime(&t_start);
}
float msTimer::elapsedMs()
{
timeb t_now;
ftime(&t_now);
return (float)(t_now.time - t_start.time) * 1000.0f +
(float)(t_now.millitm - t_start.millitm);
}
使用例:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
msTimer t;
for (int i = 0; i < 5000000; i++)
;
std::cout << t.elapsedMs() << endl;
return 0;
}
コンピューターの出力は「19」です。 msTimer
クラスの精度は、ミリ秒のオーダーです。上記の使用例では、for
- loopによって費やされた実行の合計時間が追跡されます。この時間には、マルチタスクによるmain()
の実行コンテキストのオペレーティングシステムの切り替えが含まれていました。