経過時間を簡単に測定


297

私はtime()を使用しようとしていますてプログラムのさまざまなポイントを測定ています。

わからないのは、変更前と変更後の値が同じなのはなぜですか。これは私のプログラムのプロファイルを作成するための最良の方法ではないことを理解しています。何か時間がかかるのを確認したいだけです。

printf("**MyProgram::before time= %ld\n", time(NULL));

doSomthing();
doSomthingLong();

printf("**MyProgram::after time= %ld\n", time(NULL));

私が試してみました:

struct timeval diff, startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

timersub(&endTV, &startTV, &diff);

printf("**time taken = %ld %ld\n", diff.tv_sec, diff.tv_usec);

の結果をどのように読み**time taken = 0 26339ますか?つまり、26,339ナノ秒= 26.3ミリ秒ということですか。

について**time taken = 4 45025はどうですか、それは4秒と25ミリ秒を意味しますか?


10
質問が理解できません。もちろん値は異なります。間に時間が経過したためtime()、別の値を返します。
トーマス

1
「前と後の値が違うのはなぜかわからない」とはどういう意味ですか?現在の時刻(1970年1月1日からの秒数)を取得してtime(NULL)います... 2回目に呼び出すと、最初の時刻からN秒後になり、したがって...異なっていますt完了するまでに少し時間がかかります...その場合、それは最初のものと同じになります)。
ブライアンローチ

1
何が印刷されるのか、ストップウォッチや壁掛け時計(またはカレンダー)で計時する場合の所要時間を教えてください。
Matt Curtis、

4
申し訳ありませんが、どちらの値も同じです。質問を間違って入力しました。
hap497

2
このスレッドを参照してください。stackoverflow.com/questions/275004/...
デフォルトの

回答:


336
//***C++11 Style:***
#include <chrono>

std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();

std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "[µs]" << std::endl;
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::nanoseconds> (end - begin).count() << "[ns]" << std::endl;

10
ええ、これが答えになるはずです
フェレンツダッカ

23
あなたが追加する必要があり、これを実行するには#include <chrono>:ディレクティブをし、私のように、報告時間を変更しますstd::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;:(およびC ++のコンパイル11フラグを忘れないでください-std=c++11
アントネッロ・

1
ちなみに、これは実時間ではなく、CPU時間を測定します。正しい?
ニコス2017年

4
@ RestlessC0bra cppreferenceのドキュメントによると、「この時計は実時間とは関係なく(たとえば、最後の再起動からの時間である可能性があります)、間隔の測定に最適です。」
cylus

1
これはどのデータタイプですか?std :: chrono :: duration_cast <std :: chrono :: microseconds>(end-begin).count()
sqp_125

272
#include <ctime>

void f() {
  using namespace std;
  clock_t begin = clock();

  code_to_time();

  clock_t end = clock();
  double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
}

このtime()関数は1秒以内の精度しかありませんがCLOCKS_PER_SEC、1秒以内に「クロック」があります。非常に単純化されていますが、これは簡単でポータブルな測定です。


129
clock()は実際の経過時間ではなく、CPU時間を測定することに注意してください(これはかなり長い場合があります)。
jlstrecker 2013年

12
クラスターの並列コードをプログラミングする場合、この方法は実際の時間を反映しません...
ニコラスハミルトン

3
これが最も簡単な方法のようです。@jlstreckerのコメントを更新または対処しますか?
Lorah Attkins、2015年

5
上記のソリューションは、多くの理由で適切なソリューションではありません。-これが正解ですstackoverflow.com/questions/2962785/...
Xofo

1
私はこの解決策を試しました、そしてコメントが示唆したように、私のタイマーは実世界の時間よりもはるかに速く走りました。
RTbecard 2017

267

あなたのことができ、時間が計測機構抽象的で測定し、各呼び出し可能の実行時間を持って、最小限の余分なコードだけタイマー構造を介して呼び出されることで、。さらに、コンパイル時にタイミングタイプ(ミリ秒、ナノ秒など)をパラメーター化できます。

Loki Astariによるレビューと可変部テンプレートの使用の提案に感謝します。 これが、転送された関数呼び出しの理由です。

#include <iostream>
#include <chrono>

template<typename TimeT = std::chrono::milliseconds>
struct measure
{
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F&& func, Args&&... args)
    {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                            (std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

int main() {
    std::cout << measure<>::execution(functor(dummy)) << std::endl;
}

Demo

ハワードヒナンによるコメントによると、クロノシステムから脱出するまでは、脱出しないことが最善です。したがって、上記のクラスはcount、追加の静的メソッド(C ++ 14に示されている)を提供することにより、ユーザーに手動で呼び出す選択肢を与えることができます

template<typename F, typename ...Args>
static auto duration(F&& func, Args&&... args)
{
    auto start = std::chrono::steady_clock::now();
    std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
    return std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now()-start);
} 

// call .count() manually later when needed (eg IO)
auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2.0;

そして、そのクライアントにとって最も役立つ

「I / O(平均など)の前に一連の期間を後処理したい」


完全なコードはここにあります。クロノに基づいてベンチマークツールを構築しようとする私の試みがここに記録されています


C ++ 17 std::invokeが利用可能な場合、呼び出し可能オブジェクトの呼び出しexecutionは次のように行うことができます。

invoke(forward<decltype(func)>(func), forward<Args>(args)...);

メンバー関数へのポインターである呼び出し可能オブジェクトを提供します。


2
いいね。私のコードには似たようなものがありますが、クラスへの別のインターフェイスを使用しています。コンストラクターでcode_timer開始時間(std::chrono::system_clock::now();)を取るクラス()があります。これはcode_timer::ellapsed、新しいnow()呼び出しとコンストラクターの呼び出しの違いを測定するメソッドです、およびcode_timer::reset開始時間を新しいnow()結果にリセットするメソッド。コード内のファンクターの実行を測定するために、クラスの外でフリー関数を使用します。これにより、オブジェクトの構築から非同期呼び出しの終了までの時間を測定できます。
utnapistim 2014年

7
<nitpick>:chrono必要になるまでシステムから脱出しないでください(の使用は避けてください.count())。.count()強制されたときにクライアントが呼び出せるようにします(I / Oについては、これは本当に残念です)。クライアントは、I / O(平均など)の前に一連の期間を後処理する場合がありますが、これはchronoシステム内で行うのが最適です。
ハワードヒンナン、2015年

1
@ user3241228 1. VS2013は自動戻り値タイプをサポートしていません(末尾の戻り値タイプのみ-これはまだ使用できないc ++ 14機能です)。2. これが理由だと思いますが、念のため、aqに質問しました
Nikos Athanasiou 2015年

2
なんでstd::forward<F>(func)
oliora 2016

3
@olioraそれは同じことです。構文的にそこにないstd::forward<decltype(func)>(func)一般的なラムダ(auto&& func)の引数に適用でき、ベンチマークライブラリで行うFユーティリティマクロ#define fw(arg) std::forward<decltype(arg)>(arg)で抽象化するのが簡単なので、私は好みます(そのため、構文については詳しく説明していません。答え)
ニコスアタナシウ

56

あなたの質問からわかるように、コードの実行後の経過時間を知りたいようです。秒単位で結果を確認しても問題ないと思います。もしそうなら、使用してみてくださいdifftime()以下に示す関数を。これで問題が解決することを願っています。

#include <time.h>
#include <stdio.h>

time_t start,end;
time (&start);
.
.
.
<your code>
.
.
.
time (&end);
double dif = difftime (end,start);
printf ("Elasped time is %.2lf seconds.", dif );

4
これは常に整数秒を与えます。それは起こるはずですか?
硝酸ナトリウム2014

10
時間は常に秒のみを返すため、1秒未満の測定には使用できません。
DeepDeadpool 2015

31

Windowsのみ:(この回答を投稿した後、Linuxタグが追加されました)

GetTickCount()を使用して、システムが起動してから経過したミリ秒数を取得できます。

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
Linuxで使用しています。そのため、GetTickCount()関数を使用できません。
hap497

1
もう気にしない;)投稿のタグを更新してくれてありがとう
RvdK

これは機能し、CPU時間ではなくリアルタイムを提供します。私は置くことによって、それをテストSleepEx(5000,0)の時間のかかる操作との違いを行います//の代わりにafterbefore、ほぼ5秒でした。
Ruchir 2015

14

time(NULL)1970年1月1日00:00(エポック)から経過した秒数を返します。したがって、2つの値の差は、処理にかかった秒数です。

int t0 = time(NULL);
doSomthing();
doSomthingLong();
int t1 = time(NULL);

printf ("time = %d secs\n", t1 - t0);

を使用するとgetttimeofday()、現在の時刻が秒単位で返さtime()れ、マイクロ秒単位でも返されます。


13

time(NULL)関数は、1970年1月1日00:00から経過した秒数を返します。そして、その関数はプログラム内の別の時間に呼び出されるため、C ++では常に異なる 時間になります


誰かが反対票を投じた理由はわかりませんが、あなたの答えは完全に正しくありません。手始めに、それは日付時刻を返しません、そして、それは常に異なっているというわけではありません。
マットジョイナー

12
struct profiler
{
    std::string name;
    std::chrono::high_resolution_clock::time_point p;
    profiler(std::string const &n) :
        name(n), p(std::chrono::high_resolution_clock::now()) { }
    ~profiler()
    {
        using dura = std::chrono::duration<double>;
        auto d = std::chrono::high_resolution_clock::now() - p;
        std::cout << name << ": "
            << std::chrono::duration_cast<dura>(d).count()
            << std::endl;
    }
};

#define PROFILE_BLOCK(pbn) profiler _pfinstance(pbn)

使い方は以下のとおりです::

{
    PROFILE_BLOCK("Some time");
    // your code or function
}

これは範囲がRAIIに似ています

これは私のものではありませんが、ここでは関連性があると思いました


1
欠落が含まれています
ステパンヤコヴェンコ2017

9
#include<time.h> // for clock
#include<math.h> // for fmod
#include<cstdlib> //for system
#include <stdio.h> //for delay

using namespace std;

int main()
{


   clock_t t1,t2;

   t1=clock(); // first time capture

   // Now your time spanning loop or code goes here
   // i am first trying to display time elapsed every time loop runs

   int ddays=0; // d prefix is just to say that this variable will be used for display
   int dhh=0;
   int dmm=0;
   int dss=0;

   int loopcount = 1000 ; // just for demo your loop will be different of course

   for(float count=1;count<loopcount;count++)
   {

     t2=clock(); // we get the time now

     float difference= (((float)t2)-((float)t1)); // gives the time elapsed since t1 in milliseconds

    // now get the time elapsed in seconds

    float seconds = difference/1000; // float value of seconds
    if (seconds<(60*60*24)) // a day is not over
    {
        dss = fmod(seconds,60); // the remainder is seconds to be displayed
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the remainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= hours;  // the hours to be displayed
        ddays=0;
    }
    else // we have reached the counting of days
    {
        float days = seconds/(24*60*60);
        ddays = (int)(days);
        float minutes= seconds/60;  // the total minutes in float
        dmm= fmod(minutes,60);  // the rmainder are minutes to be displayed
        float hours= minutes/60; // the total hours in float
        dhh= fmod (hours,24);  // the hours to be displayed

    }

    cout<<"Count Is : "<<count<<"Time Elapsed : "<<ddays<<" Days "<<dhh<<" hrs "<<dmm<<" mins "<<dss<<" secs";


    // the actual working code here,I have just put a delay function
    delay(1000);
    system("cls");

 } // end for loop

}// end of main 

3
回答を歓迎しますが、コードの簡単な説明を含むプリアンブルをお勧めします。ありがとう。
Kev

2
これは経過時間ではなく、プロセッサー時間です。
JonnyJD 14

8

2番目のプログラムによって出力される値は、秒とマイクロ秒です。

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs

8
#include <ctime>
#include <cstdio>
#include <iostream>
#include <chrono>
#include <sys/time.h>
using namespace std;
using namespace std::chrono;

void f1()
{
  high_resolution_clock::time_point t1 = high_resolution_clock::now();
  high_resolution_clock::time_point t2 = high_resolution_clock::now();
  double dif = duration_cast<nanoseconds>( t2 - t1 ).count();
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f2()
{
  timespec ts1,ts2;
  clock_gettime(CLOCK_REALTIME, &ts1);
  clock_gettime(CLOCK_REALTIME, &ts2);
  double dif = double( ts2.tv_nsec - ts1.tv_nsec );
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}

void f3()
{
  struct timeval t1,t0;
  gettimeofday(&t0, 0);
  gettimeofday(&t1, 0);
  double dif = double( (t1.tv_usec-t0.tv_usec)*1000);
  printf ("Elasped time is %lf nanoseconds.\n", dif );
}
void f4()
{
  high_resolution_clock::time_point t1 , t2;
  double diff = 0;
  t1 = high_resolution_clock::now() ;
  for(int i = 1; i <= 10 ; i++)
  {
    t2 = high_resolution_clock::now() ;
    diff+= duration_cast<nanoseconds>( t2 - t1 ).count();
    t1 = t2;
  }
  printf ("high_resolution_clock:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f5()
{
  timespec ts1,ts2;
  double diff = 0;
  clock_gettime(CLOCK_REALTIME, &ts1);
  for(int i = 1; i <= 10 ; i++)
  {
    clock_gettime(CLOCK_REALTIME, &ts2);
    diff+= double( ts2.tv_nsec - ts1.tv_nsec );
    ts1 = ts2;
  }
  printf ("clock_gettime:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

void f6()
{
  struct timeval t1,t2;
  double diff = 0;
  gettimeofday(&t1, 0);
  for(int i = 1; i <= 10 ; i++)
  {
    gettimeofday(&t2, 0);
    diff+= double( (t2.tv_usec-t1.tv_usec)*1000);
    t1 = t2;
  }
  printf ("gettimeofday:: Elasped time is %lf nanoseconds.\n", diff/10 );
}

int main()
{
  //  f1();
  //  f2();
  //  f3();
  f6();
  f4();
  f5();
  return 0;
}

4

C ++ std :: chronoには、クロスプラットフォームであることの明らかな利点があります。ただし、POSIXのclock_gettime()と比較して、オーバーヘッドも大幅に増加します。私のLinuxボックスでは、すべてのstd::chrono::xxx_clock::now()フレーバーのパフォーマンスはほぼ同じです。

std::chrono::system_clock::now()
std::chrono::steady_clock::now()
std::chrono::high_resolution_clock::now()

POSIX clock_gettime(CLOCK_MONOTONIC, &time)は同じでなければなりませんsteady_clock::now()が、x3倍以上高速です!

これが完全性のための私のテストです。

#include <stdio.h>
#include <chrono>
#include <ctime>

void print_timediff(const char* prefix, const struct timespec& start, const 
struct timespec& end)
{
    double milliseconds = end.tv_nsec >= start.tv_nsec
                        ? (end.tv_nsec - start.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec) * 1e3
                        : (start.tv_nsec - end.tv_nsec) / 1e6 + (end.tv_sec - start.tv_sec - 1) * 1e3;
    printf("%s: %lf milliseconds\n", prefix, milliseconds);
}

int main()
{
    int i, n = 1000000;
    struct timespec start, end;

    // Test stopwatch
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i) {
        struct timespec dummy;
        clock_gettime(CLOCK_MONOTONIC, &dummy);
    }
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("clock_gettime", start, end);

    // Test chrono system_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::system_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::system_clock::now", start, end);

    // Test chrono steady_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::steady_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::steady_clock::now", start, end);

    // Test chrono high_resolution_clock
    clock_gettime(CLOCK_MONOTONIC, &start);
    for (i = 0; i < n; ++i)
        auto dummy = std::chrono::high_resolution_clock::now();
    clock_gettime(CLOCK_MONOTONIC, &end);
    print_timediff("chrono::high_resolution_clock::now", start, end);

    return 0;
}

そして、これはgcc7.2 -O3でコンパイルしたときに得られる出力です。

clock_gettime: 24.484926 milliseconds
chrono::system_clock::now: 85.142108 milliseconds
chrono::steady_clock::now: 87.295347 milliseconds
chrono::high_resolution_clock::now: 84.437838 milliseconds

3

time(NULL)1970年1月1日は、おそらくあなたがする何を意味するか2つのタイムスタンプの差分を取るです:関数呼び出しは、秒数はEPOCてからの経過時間を返します

size_t start = time(NULL);
doSomthing();
doSomthingLong();

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);

3

他の人がすでに述べたように、C標準ライブラリのtime()関数の解像度は1秒よりも優れていません。より良い解像度を提供する可能性がある唯一の完全に移植可能なC関数は、clock()のようですが、それは実時間ではなくプロセッサ時間を測定します。自分をPOSIXプラットフォーム(Linuxなど)に制限したい場合は、clock_gettime()関数が適しています。

C ++ 11以降、より優れたタイミング機能がありますさまざまなコンパイラやオペレーティングシステム間で移植性の高い形式で優れた解像度を提供する、より利用可能になりました。同様に、boost :: datetimeライブラリは、移植性の高い優れた高解像度タイミングクラスを提供します。

これらの機能のいずれかを使用する際の1つの課題は、システムクロックを照会することによって導入される時間遅延です。clock_gettime()、boost :: datetime、std :: chronoを試してみると、この遅延は簡単にマイクロ秒単位になることがあります。したがって、コードの任意の部分の期間を測定するときは、このサイズ前後の測定エラーが発生することを許可するか、何らかの方法でそのゼロエラーを修正する必要があります。理想的には、関数によって費やされた時間の複数の測定値を収集し、平均、または多くの実行で費やされた最大/最小時間を計算したい場合があります。

これらすべての移植性と統計収集の問題を支援するために、C ++コードのタイミングブロック用のシンプルなAPIを提供し、ゼロエラーを計算し、埋め込まれた複数のタイマーから統計を報告するGithubで利用可能なcxx-rtimersライブラリを開発していますあなたのコードで。C ++ 11コンパイラー#include <rtimers/cxx11.hpp>を使用している場合は、単純に、次のようなものを使用します。

void expensiveFunction() {
    static rtimers::cxx11::DefaultTimer timer("expensiveFunc");
    auto scopedStartStop = timer.scopedStart();
    // Do something costly...
}

プログラムの終了時に、次のようなstd :: cerrに書き込まれたタイミング統計の概要が表示されます。

Timer(expensiveFunc): <t> = 6.65289us, std = 3.91685us, 3.842us <= t <= 63.257us (n=731)

これは、平均時間、その標準偏差、上限と下限、およびこの関数が呼び出された回数を示しています。

Linux固有のタイミング関数を使用したい場合#include <rtimers/posix.hpp>、またはBoostライブラリを使用しているが古いC ++コンパイラを使用している場合は、使用できます#include <rtimers/boost.hpp>。これらのタイマークラスには、複数のスレッド間で統計的なタイミング情報を収集できるバージョンもあります。また、システムクロックの2つの直接連続するクエリに関連するゼロエラーを推定できる方法もあります。


2

内部的に関数はシステムのクロックにアクセスするため、呼び出すたびに異なる値が返されます。一般に、非関数型言語では、関数の名前と引数を見ただけでは確認できない多くの副作用と隠れた状態が存在する可能性があります。


2

見たところ、tv_secは経過した秒数を格納し、tv_usecは経過したマイクロ秒を個別に格納しています。そして、それらはお互いの変換ではありません。したがって、合計時間を取得するには、適切な単位に変更して追加する必要があります。

struct timeval startTV, endTV;

gettimeofday(&startTV, NULL); 

doSomething();
doSomethingLong();

gettimeofday(&endTV, NULL); 

printf("**time taken in microseconds = %ld\n",
    (endTV.tv_sec * 1e6 + endTV.tv_usec - (startTV.tv_sec * 1e6 + startTV.tv_usec))
    );

2

Linuxでは、clock_gettime()が適切な選択肢の1つです。リアルタイムライブラリ(-lrt)をリンクする必要があります。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

#define BILLION  1000000000L;

int main( int argc, char **argv )
  {
    struct timespec start, stop;
    double accum;

    if( clock_gettime( CLOCK_REALTIME, &start) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    system( argv[1] );

    if( clock_gettime( CLOCK_REALTIME, &stop) == -1 ) {
      perror( "clock gettime" );
      exit( EXIT_FAILURE );
    }

    accum = ( stop.tv_sec - start.tv_sec )
          + ( stop.tv_nsec - start.tv_nsec )
            / BILLION;
    printf( "%lf\n", accum );
    return( EXIT_SUCCESS );
  }

2

ライブラリ内の個々の関数の実行時間を測定する必要がありました。すべての関数のすべての呼び出しを時間測定関数でラップする必要はありませんでした。醜くて呼び出しスタックが深まるからです。また、タイマーコードをすべての関数の上部と下部に配置したくありませんでした。これは、関数が早期に終了したり、例外をスローしたりするときに混乱を招くためです。結局、自分の寿命を使って時間を測定するタイマーを作ることになりました。

このように、問題のコードブロックの先頭でこれらのオブジェクトの1つをインスタンス化するだけで(コードまたは実際のスコープ)、コードブロックが費やした実時間を測定し、インスタンスデストラクタがそれ以降の経過時間を測定できるようにしますインスタンスがスコープ外になったときの構築。ここで完全な例を見つけることができますが、構造は非常に単純です:

template <typename clock_t = std::chrono::steady_clock>
struct scoped_timer {
  using duration_t = typename clock_t::duration;
  const std::function<void(const duration_t&)> callback;
  const std::chrono::time_point<clock_t> start;

  scoped_timer(const std::function<void(const duration_t&)>& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  scoped_timer(std::function<void(const duration_t&)>&& finished_callback) :
      callback(finished_callback), start(clock_t::now()) { }
  ~scoped_timer() { callback(clock_t::now() - start); }
};

構造体は、スコープから外れると、提供されたファンクターにコールバックするため、タイミング情報を使用して何かを実行できます(印刷または保存など)。さらに複雑な処理を行う必要がある場合は、引数を指定して関数をコールバックするためにstd::bindwith std::placeholdersを使用することもできます。

これを使用する簡単な例を次に示します。

void test(bool should_throw) {
  scoped_timer<> t([](const scoped_timer<>::duration_t& elapsed) {
    auto e = std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(elapsed).count();
    std::cout << "took " << e << "ms" << std::endl;
  });

  std::this_thread::sleep_for(std::chrono::seconds(1));

  if (should_throw)
    throw nullptr;

  std::this_thread::sleep_for(std::chrono::seconds(1));
}

あなたはより意図的にしたい場合は、使用することができるnewdelete明示的に開始し、あなたのためにそれを行うにはスコープに依存せずにタイマーを停止します。


1

doSomething関数はタイマーの粒度よりも速く発生するため、これらは同じです。試してください:

printf ("**MyProgram::before time= %ld\n", time(NULL));

for(i = 0; i < 1000; ++i) {
    doSomthing();
    doSomthingLong();
}

printf ("**MyProgram::after time= %ld\n", time(NULL));

1

両方の値が同じである理由は、長い手順のためですはそれほど長くかからないためです-1秒未満です。関数の最後に長いループ(for(int i = 0; i <100000000; i ++);)を追加してみて、これが問題であることを確認してから、そこから進むことができます...

上記が真であることが判明した場合、時間をより正確に測定するために、別のシステム関数(Linuxで作業していることを理解しているので、関数名についてはお答えできません)を見つける必要があります。LinuxにはGetTickCount()に似た関数があると思います。それを見つけるだけです。


1

私は通常以下を使用します:

#include <chrono>
#include <type_traits>

using perf_clock = std::conditional<
    std::chrono::high_resolution_clock::is_steady,
    std::chrono::high_resolution_clock,
    std::chrono::steady_clock
>::type;

using floating_seconds = std::chrono::duration<double>;

template<class F, class... Args>
floating_seconds run_test(Func&& func, Args&&... args)
{
   const auto t0 = perf_clock::now();
   std::forward<Func>(func)(std::forward<Args>(args)...);
   return floating_seconds(perf_clock::now() - t0);
} 

これは、非定常クロックの使用を避け、秒数を浮動小数点数として期間として使用することを除いて、@ nikos-athanasiouと同じです。


1
このtypeswitchの場合:通常high_resolution_clocksystem_clockまたはのtypedefですsteady_clock。したがってstd::conditionalis_steadyパーツがtrueの場合にトレースするhigh_resolution_clockには、どちらが(typedefする)かを選択しますsteady_clock。falseの場合は、steady_clockもう一度選択します。steady_clock最初から使用してください...
Nikos Athanasiou

@ nikos-athanasiou 5gon12ederからのコメントに完全に同意します。標準では「典型的な」ケースは必要ないため、一部のSTLは別の方法で実装される場合があります。私は自分のコードをより一般的で、実装の詳細に関係しないようにすることを好みます。
oliora 2016

必須ではありませんが、20.12.7.3で明示的に述べられてますhigh_resolution_clock may be a synonym for system_clock or steady_clock。その理由は、これはhigh_resolution_clockティック周期が最短のクロックを表すため、実装が何であれ、安定しているかどうかの2つの選択肢があるためです。実装が他の2つのクロックと異なると言うことは、どのような選択をしても、使用しないことを選択した定常(または非)クロックのより良い実装がある(定常または非クロック)と言うようなものです。良いことを知る、なぜ良いかを知る
Nikos Athanasiou

@ nikos-athanasiou特にランタイムオーバーヘッドや検出できないコンパイル時間のオーバーヘッドが発生しない場合は、100%安全であることが望まれます。必要に応じて、「may」とasstionsを使用できます。
oliora

auの友達に逆らって、「かも」に頼るのはあなたですが、自分に合っています。100%確実にこれを書き続けたい場合は、コードを使用するユーザーとユーザーが、異なるクロックの時点を移植できないように混在させないようにする方法も見つける必要があります(このタイプのスイッチが意味を持っている場合でも、プラットフォームによって動作が異なります)。楽しんで!
Nikos Athanasiou

0

OPの3つの特定の質問に答えて。

「分からないのは、変更前と変更後の値が同じなのはなぜですか。

最初の質問とサンプルコードを示しtime()、1秒の分解能を有しているので、答えは2つの機能が1秒未満で実行することをなければなりません。ただし、2つのタイマーマークが1秒の境界をまたいでいる場合、(見たところ論理的ではなく)1秒を通知することがあります。

次の例はgettimeofday()、この構造体を埋める

struct timeval {
    time_t      tv_sec;     /* seconds */
    suseconds_t tv_usec;    /* microseconds */
};

そしてその 2番目の質問は、「どのように結果を読み取るの**time taken = 0 26339ですか?それは、26,339ナノ秒= 26.3ミリ秒を意味しますか?」と尋ねます。

私の2番目の答えは、所要時間は0秒で26339マイクロ秒、つまり0.026339秒です。これは、1秒未満で実行する最初の例を裏付けています。

3番目の質問は尋ねる:「について何**time taken = 4 45025、その平均4秒と25ミリ秒のでしょうか?」

私の3番目の答えは、所要時間は4秒と45025マイクロ秒、つまり4.045025秒です。これは、OPが以前に計時した2つの機能によって実行されるタスクを変更したことを示しています。


0
#include <ctime>
#include <functional>

using namespace std;

void f() {
  clock_t begin = clock();

  // ...code to measure time...

  clock_t end = clock();

  function<double(double, double)> convtime = [](clock_t begin, clock_t end)
  {
     return double(end - begin) / CLOCKS_PER_SEC;
  };

  printf("Elapsed time: %.2g sec\n", convtime(begin, end));

}

ここで利用可能なものと同様の例ですが、追加の変換機能と印刷のみが含まれます。


0

経過時間を自動的に測定するクラスを作成しました。このリンクのコード(c ++ 11)を確認してください:https : //github.com/sonnt174/Common/blob/master/time_measure.h

クラスTimeMeasureの使用例:

void test_time_measure(std::vector<int> arr) {
  TimeMeasure<chrono::microseconds> time_mea;  // create time measure obj
  std::sort(begin(arr), end(arr));
}

単位の付いた印刷文が好きです。コードをgccとclangに移植するには何が必要ですか?(wandbox.org
ハワード

1
@HowardHinnant:アドレス指定をありがとう、gccとclangのコードも更新しました。
Sirn Nguyen Truong

0

Matlab 味付け!

ticストップウォッチタイマーを開始してパフォーマンスを測定します。この関数は、ticコマンドの実行時の内部時刻を記録します。toc関数で経過時間を表示します。

#include <iostream>
#include <ctime>
#include <thread>
using namespace std;

clock_t START_TIMER;

clock_t tic()
{
    return START_TIMER = clock();
}

void toc(clock_t start = START_TIMER)
{
    cout
        << "Elapsed time: "
        << (clock() - start) / (double)CLOCKS_PER_SEC << "s"
        << endl;
}

int main()
{
    tic();
    this_thread::sleep_for(2s);
    toc();

    return 0;
}

-4

シンプルで高速なマルチメディアライブラリであるSFMLライブラリを使用できます。クロック、ソケット、サウンド、グラフィックスなどの多くの便利で明確に定義されたクラスが含まれています。非常に使いやすく、強くお勧めします。

これはこの質問の例です。

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.