2010-09-23 29 views

cevap

0

Hiç böyle bir şey görmedim. Normalde, bir kare çerçeveyi olabildiğince hızlı hale getirirsiniz, ya da bir sonraki işlemciyi ön-işleme ve bir sonraki işlemden geçirirsiniz, böylece kullanım noktaları% 0 ile% 100 arasındadır. Sadece nadiren FPS bir maksimum sayı ile sınırlıdır ve sadece bu durumda anlamlı bir sayı olur.

2

Nope. Oldukça paralel bir ortamda titizlikle tanımlamak bile zor. Ancak, ARB_timer_query uzantısı ile yaklaşık olarak tahmin edebilirsiniz.

+1

, kullanım ARB_timer_query uzantısı örneği verebilir misiniz? – Newbie

4

Gerçekten değil, satıcınızın yardımcı programlarını kullanarak farklı performans sayaçları alabilirsiniz, NVIDIA için NVPerfKit ve NVPerfHUD var. Diğer satıcılar benzer kuruluşlara sahiptir.

1

OpenGL oluşturma iş parçacığı uygulamasında bir zamanlayıcı sorgu tabanlı GPU yürütme zamanı ölçüm çerçevesi uyguladık. Sadece eşit 60 her seferinde 0 çerçeveleri

olduğunu

  • enqueue render iplik
  • limiter.frame60 üzerinde bir işlevi çalıştırır varsayalım: Ben zamanlayıcı sorgu parçalar aşağıda paylaşacağım Kod:

    ...

    TimerQueryQueue timerQueryQueue; 
    

    ... İşte

    void GlfwThread::beginTimerQuery(std::string description) 
    { 
        if (limiter.frame60 != 0) 
         return; 
    
        enqueue([this](std::string const& description) { 
         GLuint id; 
         glGenQueries(1, &id); 
         timerQueryQueue.push_back({ description, id }); 
         glBeginQuery(GL_TIME_ELAPSED, id); 
        }, std::move(description)); 
    } 
    
    void GlfwThread::endTimerQuery() 
    { 
        if (limiter.frame60 != 0) 
         return; 
    
        enqueue([this]{ 
         glEndQuery(GL_TIME_ELAPSED); 
        }); 
    } 
    
    
    void GlfwThread::dumpTimerQueries() 
    { 
        while (!timerQueryQueue.empty()) 
        { 
         TimerQuery& next = timerQueryQueue.front(); 
    
         int isAvailable = GL_FALSE; 
         glGetQueryObjectiv(next.timer, 
              GL_QUERY_RESULT_AVAILABLE, 
              &isAvailable); 
         if (!isAvailable) 
          return; 
    
         GLuint64 ns; 
         glGetQueryObjectui64v(next.timer, GL_QUERY_RESULT, &ns); 
    
         DebugMessage("timer: ", 
            next.description, " ", 
            std::fixed, 
            std::setprecision(3), std::setw(8), 
            ns/1000.0, Stopwatch::microsecText); 
    
         glDeleteQueries(1, &next.timer); 
    
         timerQueryQueue.pop_front(); 
        } 
    } 
    

    bazı örnek çıktısı:

    Framerate t=5.14 fps=59.94 fps_err=-0.00 aet=2850.67μs adt=13832.33μs alt=0.00μs cpu_usage=17% 
    instanceCount=20301 parallel_μs=2809 
    timer: text upload range 0.000μs 
    timer: clear and bind 95.200μs 
    timer: upload 1.056μs 
    timer: draw setup 1.056μs 
    timer: draw 281.568μs 
    timer: draw cleanup 1.024μs 
    timer: renderGlyphs 1.056μs 
    Framerate t=6.14 fps=59.94 fps_err=0.00 aet=2984.55μs adt=13698.45μs alt=0.00μs cpu_usage=17% 
    instanceCount=20361 parallel_μs=2731 
    timer: text upload range 0.000μs 
    timer: clear and bind 95.232μs 
    timer: upload 1.056μs 
    timer: draw setup 1.024μs 
    timer: draw 277.536μs 
    timer: draw cleanup 1.056μs 
    timer: renderGlyphs 1.024μs 
    Framerate t=7.14 fps=59.94 fps_err=-0.00 aet=3007.05μs adt=13675.95μs alt=0.00μs cpu_usage=18% 
    instanceCount=20421 parallel_μs=2800 
    timer: text upload range 0.000μs 
    timer: clear and bind 95.232μs 
    timer: upload 1.056μs 
    timer: draw setup 1.056μs 
    timer: draw 281.632μs 
    timer: draw cleanup 1.024μs 
    timer: renderGlyphs 1.056μs 
    

    Bu benim opengl aramaları ya da her neyse çizmeden önce bana renderThread->beginTimerQuery("draw some text"); aramaya izin verir ve Geçen GPU yürütme süresini ölçmek için hemen ardından renderThread->endTimerQuery();.

    Buradaki fikir, ölçülen bölümden hemen önce GPU komut kuyruğuna bir komut verir, bu nedenle glBeginQueryTIME_ELAPSED bazı uygulama tanımlı sayaçların değerini kaydeder. glEndQuery, geçerli sayım ile TIME_ELAPSED sorgusunun başlangıcında depolanan arasındaki farkı depolamak için bir GPU komutu verir. Bu sonuç, sorgu nesnesinde GPU tarafından saklanır ve bazı zaman uyumsuz gelecek zamanda "kullanılabilir" olur. Kodum düzenlenmiş zamanlayıcı sorgularının kuyruğunu tutar ve bitmiş ölçümler için saniyede bir kez kontrol eder. Benim dumpTimerQueue, kuyruk başındaki zamanlayıcı sorgu hala kullanılabilir olduğu sürece ölçümleri yazdırmaya devam ediyor. Sonunda, henüz mevcut olmayan ve yazdırma mesajlarını durduran bir zamanlayıcıya ulaşır.

    Ölçüm işlevlerine yapılan 60 çağrıdan 59'unu düşürdüğü ek bir özellik ekledim, böylece programımdaki tüm enstrümantasyon için yalnızca saniyede bir ölçer. Bu, çok fazla spam'i önler ve geliştirme için stdout'a dökülmeyi sağlar ve ölçümlerin neden olduğu çok fazla parazitlenmeyi önler. Limiter.frame60 olayı budur, frame60'ın < 60 olması garanti edilir.

    Bu, soruyu tam olarak yanıtlayamasa da, tüm çizim çağrılarının geçen duvar saatine göre geçen süreye dikkat ederek GPU kullanımını öğrenebilirsiniz. Çerçeve 16ms ise ve TIME_ELAPSED sorgulayıcı 8ms ise, yaklaşık% 50 GPU kullanımı elde edebilirsiniz.

    Bir not daha: GPU sırasına GPU komutları koyarak, ölçüm GPU yürütme süresi ölçülür. İş parçacığının bununla hiçbir ilgisi yoktur, eğer bu enqueue içindeki işlemler tek bir iş parçacığı içinde yürütüldüyse, eşdeğer olur.

İlgili konular