SORU
28 EYLÜL 2009, PAZARTESİ


C Çapraz Platform Yüksek Çözünürlüklü Zamanlayıcı

C basit bir zamanlayıcı mekanizması uygulamak için arıyorum . Kodu Windows ve Linux içinde çalışması gerekir. Çözünürlüğü mümkün olduğunca kesin (en azından milisaniye doğruluk) olmalıdır. Bu sadece zaman değil, uygulamak için olay odaklı tasarım, her türlü geçişini izlemek için kullanılacak. Bunu yapmak için en iyi araç nedir?

CEVAP
2 NİSAN 2011, CUMARTESİ


Eski bir soru için güncelleştirilmiş cevap:

C 11 portably yüksek çözünürlüklü zamanlayıcı ile alabilirsiniz:

#include <iostream>
#include <chrono>
#include "chrono_io"

int main()
{
    typedef std::chrono::high_resolution_clock Clock;
    auto t1 = Clock::now();
    auto t2 = Clock::now();
    std::cout << t2-t1 << '\n';
}

Örnek çıktı:

74 nanoseconds
< . p ^"chrono_io" bu yeni tür ile I/O sorunları kolaylıkla ve serbestçe kullanılabilir bir uzantısıdır here.

Ayrıca <chrono> destek mevcut uygulaması (hala serbest olan ucundan gövde, emin değilim olabilir) var.

Güncelleme

Bu std::chrono::high_resolution_clock sonraki aramalar için VS11 birkaç milisaniye sürer Ben yorum aşağıda verilen bir cevaptır. Aşağıda <chrono>-uyumlu bir çözüm. Ancak sadece Intel donanım üzerinde çalışır, satır içi derleme (compiler ile değişir bunu sözdizimi) içine daldırın ve saatin içine makinenin hızı kablo için:

#include <chrono>

struct clock
{
    typedef unsigned long long                 rep;
    typedef std::ratio<1, 2800000000>          period; // My machine is 2.8 GHz
    typedef std::chrono::duration<rep, period> duration;
    typedef std::chrono::time_point<clock>     time_point;
    static const bool is_steady =              true;

    static time_point now() noexcept
    {
        unsigned lo, hi;
        asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
        return time_point(duration(static_cast<rep>(hi) << 32 | lo));
    }

private:

    static
    unsigned
    get_clock_speed()
    {
        int mib[] = {CTL_HW, HW_CPU_FREQ};
        const std::size_t namelen = sizeof(mib)/sizeof(mib[0]);
        unsigned freq;
        size_t freq_len = sizeof(freq);
        if (sysctl(mib, namelen, &freq, &freq_len, nullptr, 0) != 0)
            return 0;
        return freq;
    }

    static
    bool
    check_invariants()
    {
        static_assert(1 == period::num, "period must be 1/freq");
        assert(get_clock_speed() == period::den);
        static_assert(std::is_same<rep, duration::rep>::value,
                      "rep and duration::rep must be the same type");
        static_assert(std::is_same<period, duration::period>::value,
                      "period and duration::period must be the same type");
        static_assert(std::is_same<duration, time_point::duration>::value,
                      "duration and time_point::duration must be the same type");
        return true;
    }

    static const bool invariants;
};

const bool clock::invariants = clock::check_invariants();

Taşınabilir değil yani. Ama eğer kendi ıntel donanım üzerinde yüksek çözünürlüklü bir saat ile deneme istiyorsanız, bu daha iyi almaz. Önceden uyarayım ama, bugün saat hızları dinamik olarak değiştirebilir (gerçekten bir derleme zamanı sabiti değil mi). Ve çok işlemcili bir makine ile bile farklı işlemciler zaman damgaları alabilirsiniz. Ama yine de, benim donanım üzerinde deneyler oldukça iyi iş. Eğer milisaniye çözünürlük ile sıkışmış iseniz, bu geçici bir çözüm olabilir.

Bu saat senin cpu saat hızını belirtildiği gibi) açısından bir süresi vardır. I. e. her saniyenin 1/2,, 800 000,000 kez bunu benim için saat işlemeye başladı. Eğer isterseniz, nanosaniye (örneğin) için bu dönüştürebilirsiniz:

using std::chrono::nanoseconds;
using std::chrono::duration_cast;
auto t0 = clock::now();
auto t1 = clock::now();
nanoseconds ns = duration_cast<nanoseconds>(t1-t0);

Dönüşüm cpu döngüsü kesirleri nanosaniye form olarak keser. Başka yuvarlama modları mümkündür, ama bu farklı bir konu.

Benim için bu süre 6 nano saniye keser, 18 saat çalışıp, düşük dönecektir.

Bazı "sabit" clock::period doğru olup olmadığını kontrol ediyor yukarıdaki saati, makine için. kontrol ekledim Yine, bu kod taşınabilir değildir, ama eğer bu saat kullanıyorsanız, zaten taahhüt ettik. get_clock_speed() özel işlevi burada gösterildiği OS X üzerinde maksimum cpu frekansı alır ve clock::period sürekli payda aynı sayı olmalıdır.

Bu eklediğiniz yeni makine için bu kodu bağlantı noktası küçük bir hata ayıklama zaman kazanmak ve yeni makine hızı clock::period güncelleme unutmayın. Tüm denetimi ya da program başlangıç sırasında derleme zamanı ya da yapılır. En azından clock::now() performans etkisi olmayacaktır.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Elly

    Elly

    3 EKİM 2005
  • Jonnyriddlin1

    Jonnyriddlin

    4 Ocak 2007
  • Plugable

    Plugable

    19 Mayıs 2010