348

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 ミリ秒ということですか?

4

25 に答える 25

297

0 - デルタ

デルタ関数を使用して時間差を計算します。

auto start = std::chrono::steady_clock::now();
std::cout << "Elapsed(ms)=" << since(start).count() << std::endl;

since任意のタイムポイントを受け入れ、任意の期間を生成します (デフォルトはミリ秒です)。次のように定義されています。

template <
    class result_t   = std::chrono::milliseconds,
    class clock_t    = std::chrono::steady_clock,
    class duration_t = std::chrono::milliseconds
>
auto since(std::chrono::time_point<clock_t, duration_t> const& start)
{
    return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}

Demo

1 - タイマー

以下に基づいてタイマーを使用しstd::chronoます。

Timer clock; // Timer<milliseconds, steady_clock>

clock.tick();
/* code you want to measure */
clock.tock();

cout << "Run time = " << clock.duration().count() << " ms\n";

Demo

Timerと定義されている:

template <class DT = std::chrono::milliseconds,
          class ClockT = std::chrono::steady_clock>
class Timer
{
    using timep_t = typename ClockT::time_point;
    timep_t _start = ClockT::now(), _end = {};

public:
    void tick() { 
        _end = timep_t{}; 
        _start = ClockT::now(); 
    }
    
    void tock() { _end = ClockT::now(); }
    
    template <class T = DT> 
    auto duration() const { 
        gsl_Expects(_end != timep_t{} && "toc before reporting"); 
        return std::chrono::duration_cast<T>(_end - _start); 
    }
};

Howard Hinnantが指摘したように、duration を使用して型システムにとどまり、平均chrono化や比較などの操作を実行します (たとえば、ここでは を使用することを意味しstd::chrono::millisecondsます)。単に IO を実行するときはcount()、期間 (たとえば、ここではミリ秒数) の または ティックを使用します。

2 - 計装

任意の呼び出し可能 (関数、関数オブジェクト、ラムダなど) をベンチマーク用に計測できます。F引数で呼び出し可能な関数があるとしますarg1,arg2。この手法の結果は次のようになります。

cout << "F runtime=" << measure<>::duration(F, arg1, arg2).count() << "ms";

Demo

measureと定義されている:

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

(1) で述べたように、持続時間 w/o を使用することは.count()、I/O の前に一連の持続時間を後処理したいクライアントにとって最も便利です。

auto avg = (measure<>::duration(func) + measure<>::duration(func)) / 2;
std::cout << "Average run time " << avg.count() << " ms\n";

+これが転送された関数呼び出しの理由です。

+完全なコードはここにあります

+ chrono に基づいてベンチマーク フレームワークを構築する試みは、ここに記録されています

+古いデモ

于 2014-02-24T18:13:40.377 に答える
284
#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 秒以内の「時計」があります。これは単純化されすぎていますが、簡単でポータブルな測定です。

于 2010-05-11T06:34:45.367 に答える
59

あなたの質問からわかるように、コードの実行後の経過時間を知りたいようです。結果が数秒で表示されるのは快適だと思います。その場合は、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 );
于 2010-05-11T07:57:33.573 に答える
32

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

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

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();
于 2010-05-11T06:22:02.880 に答える
17
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 に似ています

これは私のものではないことに注意してください。

于 2016-06-03T06:46:21.637 に答える
15

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()マイクロ秒単位でも返します。

于 2010-05-11T06:18:10.627 に答える
13

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

于 2010-05-11T06:08:13.690 に答える
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 
于 2012-09-15T14:07:28.543 に答える
8

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

0 26339 = 0.026'339 s =   26339 µs
4 45025 = 4.045'025 s = 4045025 µs
于 2010-05-11T07:19:03.760 に答える
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;
}
于 2016-12-03T12:28:12.747 に答える
3

関数呼び出しは、time(NULL)エポック: 1970 年 1 月 1 日から経過した秒数を返します。おそらく、2 つのタイムスタンプの差を取ることを意味します。

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

printf ("**MyProgram::time elapsed= %lds\n", time(NULL) - start);
于 2010-05-11T06:29:25.233 に答える
3

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()

POSIXclock_gettime(CLOCK_MONOTONIC, &time)は同じはずですsteady_clock::now()が、3 倍以上高速です。

完全を期すために、これが私のテストです。

#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
于 2018-03-12T13:02:58.803 に答える
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))
    );
于 2015-01-26T09:50:30.033 に答える
2

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

于 2010-05-11T06:17:18.553 に答える
1

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

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

于 2010-05-11T06:35:59.640 に答える
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 が提案したものと同じですが、安定していないクロックの使用を避け、持続時間として浮動秒数を使用する点が異なります。

于 2016-02-15T11:52:41.880 に答える
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));
于 2010-05-11T06:28:07.970 に答える
1

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;
}
于 2020-03-02T19:25:58.377 に答える
0

OPの3つの具体的な質問への回答。

「私が理解できないのは、なぜ前と後の値が同じなのかということです。 」

最初の質問とサンプル コードはtime()、1 秒の分解能があることを示しているため、答えは 2 つの関数が 1 秒未満で実行される必要があります。しかし、2 つのタイマー マークが 1 秒の境界にまたがっている場合、(明らかに非論理的に) 1 秒を通知することがあります。

次の例gettimeofday()では、この構造体を埋めるために which を使用します

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

2 番目の質問は次のとおりです**time taken = 0 26339

私の 2 番目の答えは、かかった時間は 0 秒で、26339 マイクロ秒、つまり 0.026339 秒です。これは、最初の例が 1 秒未満で実行されたことを示しています。

3 番目の質問は、 「では**time taken = 4 45025、4 秒と 25 ミリ秒ということですか?」

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

于 2015-01-26T20:27:07.733 に答える