Geçen süreyi kolayca ölçün


298

Zamanı kullanmaya çalışıyorum ()Programımın çeşitli noktalarını ölçmek .

Anlamadığım şey, önceki ve sonraki değerlerin neden aynı olduğudur? Bunun programımı profillendirmenin en iyi yolu olmadığını anlıyorum, sadece bir şeyin ne kadar sürdüğünü görmek istiyorum.

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

doSomthing();
doSomthingLong();

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

Denedim:

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

Sonucunu nasıl okurum **time taken = 0 26339 ? Bu 26.339 nanosaniye = 26.3 milisaniye anlamına mı geliyor?

Ne **time taken = 4 45025demek, bu 4 saniye ve 25 milisaniyedir?


10
Soruyu anlamıyorum. Tabii ki değerler farklı. Aradan geçen süre time()farklı bir değer döndürür.
Thomas

1
"Anlamadım, önceki ve sonraki değerler neden farklı?" Şu anki saati (1 Ocak 1970'den bu yana saniyeler içinde) kullanıyorsunuz time(NULL)... ikinci kez aradığınızda, ilkinden sonra N saniye olacak ve böylece ... farklı tamamlanması bir saniye sürmez ... bu durumda, birinciyle aynı olur).
Brian Roach

1
Bize ne yazdırdığını ve bir kronometre veya duvar saati (veya takvim) ile zaman ayırmanız ne kadar zaman alacağını söyleyebilir misiniz?
Matt Curtis

4
Üzgünüm, her iki değer de aynı. Sorumu yanlış yazıyorum.
hap497

Yanıtlar:


337
//***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
evet, bu cevap olmalı
Ferenc Dajka

23
Eğer eklemek zorunda bu çalıştırmak için #include <chrono>: yönergesi ve raporlama süresini değiştirecek std::cout << "Time difference (sec) = " << (std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count()) /1000000.0 <<std::endl;: (ve C ++ derleme 11 bayrağını unutma -std=c++11)
Antonello

1
Bu arada, duvar saati süresini değil, CPU süresini ölçer. Sağ?
Nikos

4
@ RestlessC0bra Cppreference üzerindeki dokümanlara göre, "Bu saat duvar saati ile ilgili değildir (örneğin, son yeniden başlatmadan bu yana geçen süre olabilir) ve aralıkları ölçmek için en uygunudur."
silindir

1
Bu ne tür bir veri? Std :: chrono :: duration_cast <std :: chrono :: mikrosaniye> (son - başlangıç) .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()İşlevi, bir saniye içinde sadece doğrudur, ancak orada CLOCKS_PER_SEC"saatler" Bir saniye içinde. Bu, aşırı basitleştirilmiş olmasına rağmen, kolay ve taşınabilir bir ölçümdür.


129
clock()CPU zamanını ölçtüğünüze dikkat edin , geçen gerçek zamanı değil (çok daha büyük olabilir)
jlstrecker

12
Kümeler için paralel kod programlarken, bu yöntem gerçek dünya zamanını yansıtmaz ...
Nicholas Hamilton

3
Bu en kolay yol gibi görünüyor. @Jlstrecker olmak üzere yapılan yorumu güncellemek veya adreslemek ister misiniz?
Lorah Attkins

5
Yukarıda belirtilen çözüm birçok nedenden dolayı iyi bir çözüm değildir. Bu doğru cevaptır - stackoverflow.com/questions/2962785/…
Xofo

1
Bu çözümü denedim ve yorumların önerdiği gibi, zamanlayıcım gerçek dünya zamanından çok daha hızlı koştu.
RTbecard

268

Şunları yapabilirsiniz soyut zaman mekanizmasını ölçme ve her çağrılabilir en ölçülür çalışma süresi var minimal ekstra kod sadece bir zamanlayıcı yapının içinden çağrılan tarafından. Ayrıca, derleme zamanında zamanlama türünü (milisaniye, nanosaniye vb.) Parametrelendirebilirsiniz .

Tarafından incelenmek sayesinde Loki Astari ve öneri variadic şablonları kullanmak. Bu nedenle iletilen fonksiyon çağrılır.

#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

Howard Hinnant'ın yorumuna göre, mecbur kalana kadar krono sistemden kaçmamak en iyisidir. Böylece yukarıdaki sınıf, kullanıcıya countekstra bir statik yöntem (C ++ 14'te gösterilmiştir) sağlayarak manuel olarak arama yapma seçeneği verebilir.

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;

ve müşteriler için

"G / Ç öncesinde bir dizi süreyi işlemek istemek (örn. ortalama)"


Kodun tamamını burada bulabilirsiniz . Chrono tabanlı bir karşılaştırma aracı oluşturma girişimim burada kaydedildi .


C ++ std::invoke17'ler mevcutsa, çağrılabilirin çağrılması executionşu şekilde yapılabilir:

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

üye işlevlerine işaret eden callables sağlamak.


2
Güzel; Kodumda benzer bir şey var, ama sınıfa farklı bir arabirim kullanın: Ben yapıcı, yeni bir çağrı ve yapıcı biri arasındaki farkı ölçen bir yöntem code_timerbaşlangıç ​​zamanı ( std::chrono::system_clock::now();) alan bir class ( ) var ve başlangıç ​​zamanını yeni bir sonuca sıfırlayan bir yöntem . Kodumdaki bir işlev yürütücüyü ölçmek için sınıfın dışında serbest bir işlev kullanıyorum. Bu, bir nesnenin yapımından bir asenkron çağrısının bitimine kadar geçen sürenin ölçülmesine olanak tanır. code_timer::ellapsednow()code_timer::resetnow()
utnapistim

7
<nitpick>: Kullanmanız chronogerekene kadar sistemden kaçmayın (kullanmaktan kaçının .count()). Müşterinin .count()zorlandığı zaman arayın (gerçekten talihsiz olan I / O için). İstemci, G / Ç (örn. Ortalama) öncesinde bir dizi süreyi işlemek isteyebilir ve bu en iyi chronosistem içinde yapılır .
Howard Hinnant

1
@ user3241228 1. VS2013 otomatik dönüş türlerini desteklemez (sadece sondaki dönüş türlerini destekler - henüz mevcut olmayan bir c ++ 14 özelliğidir). 2. inanıyorum bu nedendir ama sadece emin olmak için aq istedi
Nikos Athanasiou

2
Neden olmasın std::forward<F>(func)?
oliora

3
@oliora Aynı şey. Tercih ediyorum, std::forward<decltype(func)>(func)çünkü sözdizimsel olarak orada olmayan jenerik lambdas ( auto&& func) argümanlarına uygulanabiliyor Fve #define fw(arg) std::forward<decltype(arg)>(arg)kıyaslama kütüphanemde yaptığım bir yardımcı makroda soyutlanabiliyor (bu yüzden üzerinde fazla durmadığım sözdizimsel bir bırakma cevap)
Nikos Athanasiou

56

Sorunuzdan da görebileceğim gibi, bir kod parçasının yürütülmesinden sonra geçen süreyi bilmek istediğiniz anlaşılıyor. Sanırım sonuçları saniyeler içinde görmek rahat olur. Öyleyse, difftime()aşağıda gösterildiği gibi işlevi kullanmayı deneyin . Umarız bu sorununuzu çözer.

#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
Bu bana her zaman tamsayı saniye verir. Bunun olması gerekiyor mu?
sodiumnitrate

10
zaman her zaman yalnızca saniye döndürür, bu nedenle alt saniye ölçümleri için kullanılamaz.
DeepDeadpool

31

Yalnızca Windows: (Bu etiketi gönderdikten sonra Linux etiketi eklendi)

Sistem başlatıldığından bu yana geçen milisaniye sayısını almak için GetTickCount () kullanabilirsiniz .

long int before = GetTickCount();

// Perform time-consuming operation

long int after = GetTickCount();

7
Linux üzerinde kullanıyorum. Bu yüzden GetTickCount () işlevini kullanamıyorum.
hap497

1
already
don't

CPU zamanını değil, gerçek zamanı verir ve verir. SleepEx(5000,0)// yerine zaman harcayarak test ettim Zaman alıcı operasyon ve fark gerçekleştirin afterve beforeneredeyse 5 saniye oldu.
Ruchir

14

time(NULL)01/01/1970 tarihinden bu yana 00: 00'da ( Epoch ) geçen saniye sayısını döndürür . İki değer arasındaki fark, işleminizin kaç saniye sürdüğüdür.

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

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

Şu getttimeofday()anki zamanı saniyeler içinde time()ve mikrosaniye olarak döndüren daha iyi sonuçlar alabilirsiniz .


13

time (NULL) işlevi 01/01/1970 tarihinden sonra 00: 00'da geçen saniye sayısını döndürür. Ve bu işlev programınızda farklı zamanlarda çağrıldığından, C ++ ' da her zaman farklı olacaktır.


Birinin neden reddedildiğini bilmiyorum, ancak cevabınız tamamen doğru değil. Yeni başlayanlar için tarih saatini döndürmez ve her zaman farklı olmaz.
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)

Kullanım aşağıda ::

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

Bu kapsamdaki RAII'ye benzer

NOT bu benim değil, ama burada alakalı olduğunu düşündüm


1
eksik içerir
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
Cevabınız takdir edilirken, kodun kısa bir açıklamasını içeren bir ön amble'ı tercih ediyoruz. Teşekkürler.
Kev

2
Bu geçen zaman değil, işlemci zamanı.
JonnyJD

8

İkinci programınız tarafından yazdırılan değerler saniye ve mikrosaniyedir.

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, platformlar arası olmanın net bir faydasına sahiptir. Ancak, POSIX clock_gettime () ile karşılaştırıldığında önemli bir ek yük getirir. Linux kutumda tüm std::chrono::xxx_clock::now()aromalar kabaca aynıdır:

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

POSIX clock_gettime(CLOCK_MONOTONIC, &time)aynı olmalı, steady_clock::now()ancak x3 kat daha hızlı!

İşte tamlığım için testim.

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

Ve bu gcc7.2-O3 ile derlendiğimde elde ettiğim çıktı:

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)İki damgaları arasındaki farkı alacak yapmanız anlamına Belki neyi 1 Ocak 1970.: saniye sayısını döndürür işlev çağrısı EPOC itibaren geçen:

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

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

3

Diğerlerinin de belirttiği gibi, C standart kitaplığındaki time () işlevi bir saniyeden daha iyi bir çözünürlüğe sahip değildir. Daha iyi çözünürlük sağlayabilen tek tamamen taşınabilir C işlevinin saat () olduğu görülür, ancak bu, duvar saati yerine işlemci süresini ölçer. Eğer kişi kendini POSIX platformlarıyla (ör. Linux) sınırlandıracak içerikse, clock_gettime () fonksiyonu iyi bir seçimdir.

C ++ 11'den bu yana, farklı derleyiciler ve işletim sistemleri arasında çok taşınabilir olması gereken bir biçimde daha iyi çözünürlük sunan daha iyi zamanlama olanakları mevcuttur. Benzer şekilde boost :: datetime kütüphanesi, yüksek düzeyde taşınabilir olması gereken iyi yüksek çözünürlüklü zamanlama sınıfları sağlar.

Bu olanaklardan herhangi birinin kullanılmasındaki zorluklardan biri, sistem saatinin sorgulanmasıyla ortaya çıkan zaman gecikmesidir. Clock_gettime (), boost :: datetime ve std :: chrono ile denemeler yaparak , bu gecikme mikrosaniye ile ilgili olabilir. Bu nedenle, kodunuzun herhangi bir bölümünün süresini ölçerken, bu boyutta bir ölçüm hatası olmasına izin vermeniz veya bu sıfır hatayı bir şekilde düzeltmeye çalışmanız gerekir. İdeal olarak, fonksiyonunuz tarafından alınan zamanın çoklu ölçümlerini toplamak ve birçok çalışma boyunca ortalama veya maksimum / minimum süreyi hesaplamak isteyebilirsiniz.

Yardım için tüm bu taşınabilirlik ve istatistik toplama sorunları, ben üzerine kütüphane mevcuttur cxx-rtimers gelişmekte oldum Github sıfır hataları bilgisayar, C ++ kod zamanlama blokları için basit bir API sağlamaya çalışır ve çoklu sayaçları da istatistikler raporlama gömülü kodunuzda. Bir C ++ 11 derleyiciniz varsa, basitçe #include <rtimers/cxx11.hpp>ve şöyle bir şey kullanın:

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

Program çıkışında, std :: cerr'e yazılan zamanlama istatistiklerinin bir özetini alırsınız, örneğin:

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

ortalama süreyi, standart sapmasını, üst ve alt limitleri ve bu fonksiyonun kaç kez çağrıldığını gösterir.

Linux'a özgü zamanlama işlevlerini kullanmak istiyorsanız #include <rtimers/posix.hpp>, veya Boost kitaplıklarınız varsa ancak daha eski bir C ++ derleyiciniz varsa bunu yapabilirsiniz #include <rtimers/boost.hpp>. Bu zamanlayıcı sınıflarının birden çok iş parçacığından istatistiksel zamanlama bilgisi toplayabilen sürümleri de vardır. Ayrıca, sistem saatinin hemen ardışık iki sorgusuyla ilişkili sıfır hatasını tahmin etmenizi sağlayan yöntemler de vardır.


2

Dahili olarak fonksiyon sistemin saatine erişir, bu yüzden her aradığınızda farklı değerler döndürür. Genel olarak, işlevsel olmayan dillerle, işlevlerde yalnızca işlevin adına ve bağımsız değişkenlerine bakarak göremediğiniz birçok yan etki ve gizli durum olabilir.


2

Göründüğünden, tv_sec geçen saniyeyi depolarken tv_usec mikrosaniye ayrı ayrı saklanır. Ve bunlar birbirlerinin dönüşümü değil. Bu nedenle, geçen toplam süreyi elde etmek için uygun birime değiştirilmeli ve eklenmelidir.

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'ta, clock_gettime () iyi seçeneklerden biridir. Gerçek zamanlı kitaplığı (-lrt) bağlamanız gerekir.

#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

Bir kütüphane içindeki münferit fonksiyonların çalışma zamanını ölçmem gerekiyordu. Çirkin ve çağrı yığınını derinleştirdiği için her fonksiyonun her çağrısını bir zaman ölçüm fonksiyonu ile sarmak istemedim. Ayrıca, zamanlayıcı kodunu her işlevin üstüne ve altına koymak istemedim çünkü işlev erken çıkabileceği veya istisnalar atabileceği zaman karışıklık yaratıyor. Böylece yaptığım şey, zamanı ölçmek için kendi ömrünü kullanan bir zamanlayıcı yapmaktı.

Bu şekilde, söz konusu kod bloğunun başında (işlev veya herhangi bir kapsam) bu nesnelerden birini somutlaştırarak ve daha sonra örnek yıkıcısının geçen süreyi ölçmesine izin vererek, bir duvar bloğunu ölçebilirim. örnek kapsam dışına çıktığında. Tam örneği burada bulabilirsiniz, ancak yapı son derece basittir:

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

Yapı, kapsam dışına çıktığında sizi sağlanan işleve geri arayacaktır, böylece zamanlama bilgileriyle bir şeyler yapabilirsiniz (yazdırın veya saklayın ya da herhangi bir şey). Daha karmaşık bir şey yapmanız gerekiyorsa std::bind,std::placeholders daha argümanlarla fonksiyonlar geri çağırma için.

İşte kullanımına hızlı bir örnek:

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

Daha kasıtlı olmak istiyorsanız, siz de kullanabilirsiniz newve deleteaçıkça başlatmak ve sizin için bunu yapmak için kapsam dayanmadan sayacı durdurmak için.


1

Bunlar aynıdır çünkü doSomething işleviniz zamanlayıcının ayrıntı düzeyinden daha hızlı gerçekleşir. Deneyin:

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

Her iki değerin aynı olmasının nedeni, uzun prosedürünüzün bu kadar uzun sürmemesi - bir saniyeden az olmasıdır. Sorunun bu olduğundan emin olmak için işlevin sonuna sadece uzun bir döngü ((int i = 0; i <100000000; i ++);) eklemeyi deneyebilirsiniz, o zaman oradan gidebiliriz ...

Yukarıdaki durumun doğru olması durumunda, zamanı daha doğru ölçmek için farklı bir sistem işlevi bulmanız gerekir (linux üzerinde çalıştığınızı anlıyorum, bu nedenle işlev adıyla size yardımcı olamıyorum). Linux'ta GetTickCount () için simüler bir fonksiyon olduğundan eminim, sadece bulmanız gerekiyor.


1

Genellikle aşağıdakileri kullanırım:

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

Sabit olmayan bir saat kullanmaktan kaçınmam ve süre olarak kayan saniye kullanmam dışında önerilen @ nikos-athanasiou ile aynıdır.


1
Bu tipte anahtar : Tipik high_resolution_clockolarak system_clockveya için bir typedef'tirsteady_clock . Böylece iz std::conditionaleğer is_steadykısmı doğru, o zaman almak high_resolution_clockolduğunu (bir typedef) steady_clock. Yanlışsa, steady_clocktekrar seçersiniz . Sadece steady_clocken başından kullanın ...
Nikos Athanasiou

@ nikos-athanasiou Ben 5gon12eder'in yorumuna tamamen katılıyorum, standart tarafından "tipik" bir durum gerekmediği için bazı STL farklı bir şekilde uygulanabilir. Kodumun daha genel olmasını ve uygulama ayrıntılarıyla ilgili olmamasını tercih ederim.
oliora

Bu gerekli ama açıkça belirtildiği değil 20.12.7.3 : high_resolution_clock may be a synonym for system_clock or steady_clock. Nedeni şudur: high_resolution_clockEn kısa kene süresine sahip saatleri temsil eder, bu nedenle uygulama ne olursa olsun, sabit veya sabit olmak üzere iki seçeneği vardır. Hangi seçimi yaparsak yapalım, uygulamanın diğer iki saatten farklı olacağını söylemek, kullanmamayı tercih ettiğimiz sabit (veya değil) bir saat için daha iyi bir uygulamaya sahip olduğumuzu söylemek gibidir (sabit veya saatler için değil). Nasıl iyi olduğunu bilmek, neden daha iyi olduğunu bilmek
Nikos Athanasiou

@ nikos-athanasiou Özellikle bu bana hiçbir çalışma zamanı yükü ve tespit edilemeyen derleme zaman yükü maliyeti olduğunda% 100 güvenli olmayı tercih ederim. İsterseniz "mayıs" ve varsayımlara güvenebilirsiniz.
oliora

arkadaşımın aksine, "mayıs" a güvenen sizsiniz, ama kendinize uygun. % 100 emin olmak ve bunu yazmaya devam etmek istiyorsanız, sizin ve kodunuzun kullanıcıları için, farklı saatlerin portatif olarak karıştırılmayan zaman noktalarından kaçınmanın bir yolunu bulmalısınız (eğer bu tip anahtar bir anlam kazanırsa, farklı platformlarda farklı davranacaktır). İyi eğlenceler!
Nikos Athanasiou

0

OP'nin üç özel sorusuna cevap olarak .

"Anlamadığım şey, önceki ve sonraki değerler neden aynı? "

İlk soru ve örnek kod gösterileri time()cevabı vardır bu nedenle, 1 saniye çözünürlüğe sahip iki fonksiyon 1 saniyeden az yürütmek olacağını göstermiştir. Ancak zaman zaman (görünüşe göre mantıksız olarak) iki zamanlayıcı işaretinin bir saniye sınırına girip girmediğini 1 saniye bildirecektir .

Sonraki örnek, gettimeofday()bu yapıyı dolduran

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

ve ikinci soru soruyor: "Bir sonucu nasıl okurum **time taken = 0 26339? Bu 26.339 nanosaniye = 26.3 milisaniye anlamına mı geliyor?"

İkinci cevabım alınan sürenin 0 saniye ve 26339 mikrosaniye, yani 0.026339 saniyedir, bu da ilk örneği 1 saniyeden daha kısa sürede yürütür.

Üçüncü soru sorar: "Peki **time taken = 4 45025, o ortalama 4 saniye ile 25 milisaniye yapar?"

Üçüncü cevabım, alınan sürenin 4 saniye ve 45025 mikrosaniye, yani 4.045025 saniyedir, bu da OP'nin daha önce zamanladığı iki işlev tarafından gerçekleştirilen görevleri değiştirdiğini gösterir.


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

}

Burada mevcut olana benzer bir örnek, sadece ek dönüştürme işlevi + çıktı ile.


0

Geçen zamanı otomatik olarak ölçmek için bir sınıf oluşturdum, Lütfen bu bağlantıdaki kodu (c ++ 11) kontrol edin: https://github.com/sonnt174/Common/blob/master/time_measure.h

TimeMeasure sınıfının nasıl kullanılacağına örnek:

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

Birimlerle olan baskı beyanınızı seviyorum. Kodunuzu gcc ve clang'a taşımak için ne gerekir? ( Wandbox.org )
Howard Hinnant

1
@HowardHinnant: adresleme için teşekkürler, ben de gcc ve clang için kodu güncelledim.
Sirn Nguyen Truong

0

Matlab aromalı!

ticperformansı ölçmek için bir kronometre zamanlayıcısı başlatır. İşlev, tic komutunun yürütülmesindeki dahili zamanı kaydeder. Geçen süreyitocİşlev .

#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 kitaplığını kullanabilirsinizBasit ve Hızlı Multimedya Kütüphanesi olan . Saat, Soket, Ses, Grafik, vb.Gibi birçok kullanışlı ve iyi tanımlanmış sınıf içerir. Kullanımı çok kolay ve şiddetle tavsiye edilir.

Bu, bu soruya bir örnektir.

sf::Clock clock;
...
Time time1 = clock.getElapsedTime();
...
Time time2 = clock.restart();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.