Mudah mengukur waktu yang telah berlalu


297

Saya mencoba menggunakan waktu () untuk mengukur berbagai titik program saya.

Yang tidak saya mengerti adalah mengapa nilai-nilai di sebelum dan sesudahnya sama? Saya mengerti ini bukan cara terbaik untuk profil program saya, saya hanya ingin melihat berapa lama waktu yang dibutuhkan.

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

doSomthing();
doSomthingLong();

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

Saya telah mencoba:

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

Bagaimana cara saya membaca hasil **time taken = 0 26339? Apakah itu berarti 26.339 nanodetik = 26,3 msec?

Bagaimana **time taken = 4 45025, apakah itu berarti 4 detik dan 25 msec?


10
Saya tidak mengerti pertanyaannya. Tentu saja nilainya berbeda. Waktu berlalu di antaranya, jadi time()mengembalikan nilai yang berbeda.
Thomas

1
Apa maksud Anda "Saya tidak mengerti mengapa nilai sebelum dan sesudah berbeda"? Anda mendapatkan waktu saat ini (dalam detik sejak 1 Januari 1970) menggunakan time(NULL)... kedua kalinya Anda memanggilnya akan menjadi N detik setelah yang pertama dan dengan demikian ... berbeda (kecuali apa pun yang Anda lakukan tidak t mengambil kedua untuk menyelesaikan ... dalam hal ini, akan sama dengan yang pertama).
Brian Roach

1
Bisakah Anda memberi tahu kami apa yang tercetak, dan berapa lama jika Anda menghitungnya dengan stopwatch atau jam dinding (atau kalender)?
Matt Curtis

4
Maaf, maksud saya kedua nilai tersebut SAMA. Saya salah mengetik pertanyaan saya.
hap497

Jawaban:


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
ya, ini seharusnya jawabannya
Ferenc Dajka

23
Untuk menjalankan ini Anda harus menambahkan #include <chrono>direktif dan saya akan mengubah waktu pelaporan sebagai: std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;(dan jangan lupa C ++ 11 bendera ketika kompilasi: -std=c++11)
Antonello

1
Omong-omong, ini mengukur waktu CPU, bukan waktu jam dinding. Baik?
Nikos

4
@ RestlessC0bra Menurut dokumen di cppreference, "Jam ini tidak terkait dengan waktu jam dinding (misalnya, ini bisa menjadi waktu sejak reboot terakhir), dan paling cocok untuk mengukur interval."
silinder

1
Tipe data apa ini? Std :: chrono :: duration_cast <std :: chrono :: microseconds> (akhir - mulai) .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;
}

The time()Fungsi ini hanya akurat ke dalam kedua, tetapi ada CLOCKS_PER_SEC"jam" dalam satu detik. Ini adalah pengukuran yang mudah dan portabel, meskipun terlalu disederhanakan.


129
Sadarilah bahwa clock()mengukur waktu CPU, bukan waktu aktual yang berlalu (yang mungkin jauh lebih besar).
jlstrecker

12
Saat memprogram kode paralel untuk kluster, metode ini tidak mencerminkan waktu dunia nyata ...
Nicholas Hamilton

3
Ini sepertinya cara termudah. Apakah Anda ingin memperbarui atau mengatasi komentar yang dibuat dengan @jlstrecker?
Lorah Attkins

5
Solusi yang diposting di atas bukanlah solusi yang baik karena berbagai alasan. Ini adalah jawaban yang benar - stackoverflow.com/questions/2962785/…
Xofo

1
Saya mencoba solusi ini, dan seperti komentar yang disarankan, timer saya berjalan lebih cepat daripada waktu dunia nyata.
RTbecard

267

Anda dapat mengabstraksi mekanisme pengukuran waktu dan menjalankan setiap waktu yang dapat dipanggil dengan kode tambahan minimal , hanya dengan dipanggil melalui struktur pengatur waktu. Plus, pada waktu kompilasi Anda dapat menentukan jenis waktu (milidetik, nanodetik dll).

Terima kasih untuk ulasan oleh Loki Astari dan saran untuk menggunakan templat variadic. Inilah sebabnya mengapa panggilan fungsi diteruskan.

#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

Menurut komentar Howard Hinnant , yang terbaik adalah tidak melarikan diri dari sistem chrono sampai kita harus melakukannya. Jadi kelas di atas bisa memberi pengguna pilihan untuk menelepon countsecara manual dengan memberikan metode statis tambahan (ditunjukkan dalam 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;

dan paling bermanfaat bagi klien itu

"ingin memposting banyak proses durasi sebelum I / O (mis. rata-rata)"


Kode lengkap dapat ditemukan di sini . Upaya saya untuk membangun alat pembandingan berdasarkan chrono dicatat di sini .


Jika C ++ 17's std::invoketersedia, pemanggilan callable in executiondapat dilakukan seperti ini:

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

untuk menyediakan callable yang pointer ke fungsi anggota.


2
Bagus; Saya memiliki sesuatu yang serupa dalam kode saya, tetapi menggunakan antarmuka yang berbeda dengan kelas: Saya memiliki kelas ( code_timer) yang memerlukan waktu mulai ( std::chrono::system_clock::now();) dalam konstruktor, metode code_timer::ellapsedyang mengukur perbedaan antara now()panggilan baru dan yang ada di konstruktor , dan code_timer::resetmetode yang mengatur ulang waktu mulai ke now()hasil baru . Untuk mengukur pelaksanaan functor dalam kode saya, saya menggunakan fungsi bebas, di luar kelas. Hal ini memungkinkan untuk mengukur waktu dari pembangunan suatu objek, hingga penyelesaian panggilan asynch.
utnapistim

7
<nitpick>: Jangan keluar dari chronosistem sampai Anda harus (hindari penggunaan .count()). Biarkan klien menelepon .count()saat dipaksa (katakan untuk I / O, yang memang disayangkan). Klien mungkin ingin pasca-proses banyak durasi sebelum I / O (misalnya rata-rata) dan yang terbaik dilakukan dalam chronosistem.
Howard Hinnant

1
@ user3241228 1. VS2013 tidak mendukung tipe pengembalian otomatis (hanya mengikuti tipe pengembalian - ini adalah fitur c ++ 14 belum tersedia). 2. Saya percaya ini alasannya tapi saya minta aq hanya untuk memastikan
Nikos Athanasiou

2
Mengapa tidak std::forward<F>(func)?
oliora

3
@iora Ini adalah hal yang sama. Saya lebih suka std::forward<decltype(func)>(func)karena itu dapat berlaku untuk argumen lambdas generik ( auto&& func) di mana Ftidak ada secara sintaksis dan mudah untuk abstrak dalam makro utilitas #define fw(arg) std::forward<decltype(arg)>(arg)yang saya lakukan di perpustakaan benchmark saya (jadi itu adalah sintaksis yang tersisa di mana saya tidak menjelaskan banyak dalam jawabannya)
Nikos Athanasiou

56

Seperti yang saya lihat dari pertanyaan Anda, sepertinya Anda ingin mengetahui waktu yang telah berlalu setelah eksekusi beberapa kode. Saya kira Anda akan merasa nyaman untuk melihat hasilnya dalam hitungan detik. Jika demikian, coba gunakan difftime()fungsi seperti yang ditunjukkan di bawah ini. Semoga ini bisa menyelesaikan masalah Anda.

#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
Ini selalu memberi saya bilangan bulat detik. Apakah itu seharusnya terjadi?
sodiumnitrate

10
waktu akan selalu hanya mengembalikan detik, sehingga tidak dapat digunakan untuk pengukuran sub detik.
DeepDeadpool

31

Hanya Windows: (Tag Linux ditambahkan setelah saya memposting jawaban ini)

Anda dapat menggunakan GetTickCount () untuk mendapatkan jumlah milidetik yang berlalu sejak sistem dimulai.

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
Saya menggunakannya di linux. Jadi saya tidak bisa menggunakan fungsi GetTickCount ().
hap497

1
sudah tidak apa-apa;) Terima kasih telah memperbarui tag posting Anda
RvdK

Ini bekerja dan memberikan waktu nyata, bukan waktu CPU. Saya mengujinya dengan menempatkan SleepEx(5000,0)// melakukan operasi yang memakan waktu dan perbedaan afterdan beforehampir 5 detik.
Ruchir

14

time(NULL)mengembalikan jumlah detik yang berlalu sejak 01/01/1970 pada pukul 00:00 ( Zaman ). Jadi perbedaan antara kedua nilai tersebut adalah jumlah detik yang Anda proses.

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

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

Anda bisa mendapatkan hasil yang lebih baik getttimeofday(), yang mengembalikan waktu saat ini dalam detik, seperti time()halnya juga dalam mikrodetik.


13

fungsi waktu (NULL) akan mengembalikan jumlah detik yang berlalu sejak 01/01/1970 pada 00:00. Dan karena, fungsi itu dipanggil pada waktu yang berbeda di program Anda, itu akan selalu berbeda di C ++


Saya tidak tahu mengapa seseorang downvoted, tetapi jawaban Anda tidak sepenuhnya benar. Sebagai permulaan, itu tidak mengembalikan waktu tanggal, dan itu tidak akan selalu berbeda.
Matt Joiner

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)

Penggunaan di bawah ::

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

Ini mirip dengan ruang lingkup RAII

CATATAN ini bukan milik saya, tetapi saya pikir itu relevan di sini


1
termasuk yang hilang
Stepan Yakovenko

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
Sementara jawaban Anda dihargai, kami lebih suka pre-amble yang berisi deskripsi singkat dari kode. Terima kasih.
Kev

2
Ini bukan waktu yang berlalu, tetapi waktu prosesor.
JonnyJD

8

Nilai yang dicetak oleh program kedua Anda adalah detik, dan mikrodetik.

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 memiliki keuntungan yang jelas sebagai cross-platform. Namun, itu juga memperkenalkan overhead yang signifikan dibandingkan dengan POSIX clock_gettime (). Di kotak Linux saya semua std::chrono::xxx_clock::now()rasa berkinerja sama:

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

Padahal POSIX clock_gettime(CLOCK_MONOTONIC, &time)harus sama dengansteady_clock::now() tetapi lebih dari x3 kali lebih cepat!

Inilah tes saya, untuk kelengkapan.

#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;
}

Dan ini adalah output yang saya dapatkan ketika dikompilasi dengan 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

The time(NULL)fungsi panggilan akan mengembalikan jumlah detik berlalu sejak EPOC: 1 Januari 1970. Mungkin apa yang Anda maksud lakukan adalah mengambil perbedaan antara dua cap waktu:

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

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

3

Seperti yang telah dicatat orang lain, fungsi time () di pustaka standar C tidak memiliki resolusi yang lebih baik dari satu detik. Satu-satunya fungsi C yang sepenuhnya portabel yang dapat memberikan resolusi yang lebih baik tampaknya adalah clock (), tetapi yang mengukur waktu prosesor daripada waktu jam dinding. Jika seseorang konten untuk membatasi diri pada platform POSIX (misalnya Linux), maka fungsi clock_gettime () adalah pilihan yang baik.

Sejak C ++ 11, ada banyak fasilitas pengaturan waktu yang lebih baik yang menawarkan resolusi yang lebih baik dalam bentuk yang harus sangat portabel di berbagai kompiler dan sistem operasi. Demikian pula, pustaka boost :: datetime menyediakan kelas timing resolusi tinggi yang bagus yang sangat portabel.

Salah satu tantangan dalam menggunakan salah satu dari fasilitas ini adalah penundaan waktu yang diperkenalkan dengan menanyakan jam sistem. Dari bereksperimen dengan clock_gettime (), boost :: datetime dan std :: chrono, keterlambatan ini dapat dengan mudah menjadi masalah mikrodetik. Jadi, ketika mengukur durasi bagian mana pun dari kode Anda, Anda harus mengizinkan ada kesalahan pengukuran sekitar ukuran ini, atau mencoba untuk memperbaiki kesalahan nol dalam beberapa cara. Idealnya, Anda mungkin ingin mengumpulkan beberapa pengukuran waktu yang diambil oleh fungsi Anda, dan menghitung rata-rata, atau waktu maksimum / minimum yang diambil di banyak berjalan.

Untuk membantu semua masalah portabilitas dan pengumpulan statistik ini, saya telah mengembangkan pustaka cxx-rtimers yang tersedia di Github yang mencoba menyediakan API sederhana untuk blok waktu kode C ++, menghitung nol kesalahan, dan melaporkan statistik dari banyak timer yang disematkan dalam kode Anda. Jika Anda memiliki kompiler C ++ 11, Anda cukup #include <rtimers/cxx11.hpp>, dan menggunakan sesuatu seperti:

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

Saat keluar dari program, Anda akan mendapatkan ringkasan statistik waktu yang ditulis ke std :: cerr seperti:

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

yang menunjukkan waktu rata-rata, standar-deviasinya, batas atas dan bawah, dan berapa kali fungsi ini dipanggil.

Jika Anda ingin menggunakan fungsi waktu khusus Linux, Anda bisa #include <rtimers/posix.hpp>, atau jika Anda memiliki perpustakaan Boost tapi kompiler C ++ yang lebih tua, Anda bisa #include <rtimers/boost.hpp>. Ada juga versi kelas pengatur waktu ini yang dapat mengumpulkan informasi waktu statistik dari berbagai utas. Ada juga metode yang memungkinkan Anda untuk memperkirakan kesalahan nol yang terkait dengan dua kueri langsung berturut-turut dari jam sistem.


2

Secara internal fungsi akan mengakses jam sistem, itulah sebabnya ia mengembalikan nilai yang berbeda setiap kali Anda menyebutnya. Secara umum dengan bahasa non-fungsional, ada banyak efek samping dan status tersembunyi dalam fungsi yang tidak dapat Anda lihat hanya dengan melihat nama fungsi dan argumen.


2

Dari apa yang dilihat, tv_sec menyimpan detik berlalu sementara tv_usec menyimpan mikrodetik berlalu secara terpisah. Dan mereka bukan konversi satu sama lain. Oleh karena itu, mereka harus diubah ke unit yang tepat dan ditambahkan untuk mendapatkan total waktu yang telah berlalu.

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

Di linux, clock_gettime () adalah salah satu pilihan yang baik. Anda harus menautkan perpustakaan waktu nyata (-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

Saya perlu mengukur waktu eksekusi fungsi individu dalam perpustakaan. Saya tidak ingin harus membungkus setiap panggilan dari setiap fungsi dengan fungsi pengukuran waktu karena itu jelek dan memperdalam tumpukan panggilan. Saya juga tidak ingin meletakkan kode penghitung waktu di bagian atas dan bawah dari setiap fungsi karena membuat berantakan ketika fungsi tersebut dapat keluar lebih awal atau melempar pengecualian misalnya. Jadi apa yang akhirnya saya lakukan adalah membuat pengatur waktu yang menggunakan masa hidupnya sendiri untuk mengukur waktu.

Dengan cara ini saya dapat mengukur waktu dinding blok kode yang diambil dengan hanya instantiate salah satu objek ini di awal blok kode yang bersangkutan (fungsi atau ruang lingkup benar-benar) dan kemudian memungkinkan instance destructor untuk mengukur waktu yang berlalu sejak konstruksi ketika instance keluar dari ruang lingkup. Anda dapat menemukan contoh lengkapnya di sini tetapi structnya sangat sederhana:

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); }
};

Struct akan memanggil Anda kembali pada functor yang disediakan ketika keluar dari ruang lingkup sehingga Anda dapat melakukan sesuatu dengan informasi waktu (cetak atau simpan atau apa pun). Jika Anda perlu melakukan sesuatu yang lebih kompleks Anda bahkan bisa menggunakan std::binddengan std::placeholdersuntuk callback fungsi dengan argumen yang lebih.

Berikut adalah contoh cepat menggunakannya:

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));
}

Jika Anda ingin lebih disengaja, Anda juga dapat menggunakan newdan deleteuntuk secara eksplisit memulai dan menghentikan timer tanpa bergantung pada pelingkupan untuk melakukannya untuk Anda.


1

Mereka sama karena fungsi doSomething Anda terjadi lebih cepat daripada rincian waktu. Mencoba:

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

Alasan kedua nilai itu sama adalah karena prosedur panjang Anda Anda tidak membutuhkan waktu lama - kurang dari satu detik. Anda dapat mencoba menambahkan loop panjang (untuk (int i = 0; i <100000000; i ++);) di akhir fungsi untuk memastikan ini masalahnya, maka kita dapat pergi dari sana ...

Jika hal di atas ternyata benar, Anda akan perlu menemukan fungsi sistem yang berbeda (saya mengerti Anda bekerja di linux, jadi saya tidak dapat membantu Anda dengan nama fungsi) untuk mengukur waktu lebih akurat. Saya yakin ada fungsi simular untuk GetTickCount () di linux, Anda hanya perlu menemukannya.


1

Saya biasanya menggunakan yang berikut ini:

#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);
} 

Itu sama dengan @ nikos-athanasiou yang diusulkan kecuali bahwa saya menghindari penggunaan jam yang tidak stabil dan menggunakan jumlah detik mengambang sebagai durasi.


1
Pada typeswitch ini : Biasanya high_resolution_clockadalah typedef untuk salah satu system_clockatau steady_clock. Jadi untuk melacak bahwa std::conditionaljika is_steadybagian itu benar, maka Anda memilih yang high_resolution_clockmana (a typedef to) the steady_clock. Jika itu salah maka Anda pilih steady_clocklagi. Cukup gunakan steady_clockdari awal ...
Nikos Athanasiou

@ nikos-athanasiou Saya sepenuhnya setuju dengan komentar dari 5gon12eder bahwa kasus "tipikal" tidak diperlukan oleh standar sehingga beberapa STL dapat diimplementasikan dengan cara yang berbeda. Saya lebih suka kode saya lebih umum dan tidak terkait dengan detail implementasi.
oliora

Ini tidak diperlukan tetapi secara eksplisit dinyatakan dalam 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. Alasannya adalah ini: high_resolution_clockmewakili jam dengan periode kutu terpendek, jadi apa pun implementasinya, ia memiliki dua pilihan, stabil atau tidak. Apa pun pilihan yang kita buat, mengatakan bahwa implementasi akan berbeda dari dua jam lainnya adalah seperti mengatakan kita memiliki implementasi yang lebih baik untuk jam yang stabil (atau tidak) yang kita pilih untuk tidak menggunakan (untuk jam yang stabil atau tidak). Mengetahui bagaimana itu baik, mengetahui mengapa lebih baik
Nikos Athanasiou

@ nikos-athanasiou Saya lebih suka 100% aman terutama ketika ini membuat saya tidak ada overhead runtime dan overhead waktu kompilasi tidak terdeteksi. Anda dapat mengandalkan "mungkin" dan assamptions jika Anda mau.
oliora

au contraire sobat, itu kamu yang mengandalkan "mungkin", tapi sesuaikan diri. Jika Anda ingin menjadi 100% yakin dan terus menulis ini, Anda juga harus menemukan cara, bagi Anda dan pengguna kode Anda, untuk menghindari pencampuran titik waktu yang tidak portable dari jam yang berbeda (jika saklar jenis ini mendapatkan makna, itu akan berperilaku berbeda pada platform yang berbeda). Selamat bersenang-senang!
Nikos Athanasiou

0

Sebagai jawaban atas tiga pertanyaan spesifik OP .

"Yang tidak saya mengerti adalah mengapa nilai-nilai di sebelum dan sesudahnya sama? "

Pertanyaan pertama dan kode sampel menunjukkan bahwa time()memiliki resolusi 1 detik, jadi jawabannya adalah bahwa kedua fungsi dijalankan dalam waktu kurang dari 1 detik. Tetapi kadang-kadang itu akan (tampaknya tidak masuk akal) menginformasikan 1 detik jika tanda dua timer mengangkangi batas satu detik.

Contoh berikutnya menggunakan gettimeofday()yang mengisi struct ini

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

dan pertanyaan kedua bertanya: "Bagaimana saya membaca hasil **time taken = 0 26339? Apakah itu berarti 26.339 nanodetik = 26,3 msec?"

Jawaban kedua saya adalah waktu yang diperlukan adalah 0 detik dan 26339 mikrodetik, yaitu 0,026339 detik, yang menghasilkan contoh pertama yang dijalankan dalam waktu kurang dari 1 detik.

Pertanyaan ketiga bertanya: "Bagaimana **time taken = 4 45025, apakah itu berarti 4 detik dan 25 msec?"

Jawaban ketiga saya adalah waktu yang diambil adalah 4 detik dan 45025 mikrodetik, yaitu 4,045025 detik, yang menunjukkan bahwa OP telah mengubah tugas yang dilakukan oleh dua fungsi yang sebelumnya diatur waktunya.


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

}

Contoh serupa dengan yang tersedia di sini, hanya dengan fungsi konversi tambahan + cetak.


0

Saya telah membuat kelas untuk secara otomatis mengukur waktu yang telah berlalu, Silakan periksa kode (c ++ 11) di tautan ini: https://github.com/sonnt174/Common/blob/master/time_measure.h

Contoh cara menggunakan TimeMeasure kelas:

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

Saya suka pernyataan cetak Anda dengan unit. Apa yang diperlukan untuk port kode Anda ke gcc dan dentang? ( wandbox.org )
Howard Hinnant

1
@HowardHinnant: terima kasih sudah mengatasi, saya perbarui kode untuk gcc dan dentang juga.
Sirn Nguyen Truong

0

Matlab rasa!

ticmemulai penghitung waktu stopwatch untuk mengukur kinerja. Fungsi ini mencatat waktu internal pada pelaksanaan perintah tic. Menampilkan waktu yang berlalu dengan tocfungsi.

#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

Anda dapat menggunakan pustaka SFML , yang merupakan Pustaka Multimedia Sederhana dan Cepat. Ini mencakup banyak kelas yang berguna dan didefinisikan dengan baik seperti Jam, Soket, Suara, Grafik, dll. Ini sangat mudah digunakan dan sangat dianjurkan.

Ini adalah contoh untuk pertanyaan ini.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.