2014-02-21 12 views
9

Hier ist ein sehr einfaches Testprogramm. Wenn Vsync deaktiviert ist, läuft dieses Programm mit 100 FPS und verbraucht praktisch 0% der CPU. Wenn ich Vsync aktiviere, erhalte ich eine CPU-Auslastung von 60FPS und 25% (100% eines Kerns auf einem 4-Kern-System). Dies ist mit einer Nvidia-GPU. Die Online-Suche führte mich zu dem Vorschlag, die "Multithread-Optimierung" im Nvidia Control Panel zu deaktivieren. Dies verringert die CPU-Auslastung, aber nur auf 10%. Außerdem, wenn ich den Aufruf nach SwapBuffers in den Ruhezustand verliere, bekomme ich wieder 25% Auslastung, selbst wenn die Multithread-Optimierung deaktiviert ist. Kann jemand etwas Licht dazu bringen? Mache ich etwas falsch? Ist Nvidias OpenGL-Implementierung hoffnungslos fehlerhaft?100% CPU-Auslastung bei Verwendung von vsync (OpenGL)

#include <GLFW/glfw3.h> 
#include <thread> 
#include <cstdlib> 
#include <cstdio> 

int main(int argc, char *argv[]) 
{ 
    if(!glfwInit()) 
     exit(EXIT_FAILURE); 

    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); 

    GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Vsync Test", nullptr, nullptr); 

    if(!window) 
    { 
     glfwTerminate(); 
     exit(EXIT_FAILURE); 
    } 

    glfwMakeContextCurrent(window); 

#ifdef USE_VSYNC 
    glfwSwapInterval(1); 
#else 
    glfwSwapInterval(0); 
#endif 

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 

    double lastTime = glfwGetTime(); 
    double nbFrames = 0; 

    while(!glfwWindowShouldClose(window)) 
    { 
     double currentTime = glfwGetTime(); 
     nbFrames++; 
     if (currentTime - lastTime >= 1.0) 
     { 
      char cbuffer[50]; 
      snprintf(cbuffer, sizeof(cbuffer), "OpenGL Vsync Test [%.1f fps, %.3f ms]", nbFrames, 1000.0/nbFrames); 
      glfwSetWindowTitle(window, cbuffer); 
      nbFrames = 0; 
      lastTime++; 
     } 
     glClear(GL_COLOR_BUFFER_BIT); 
     glfwSwapBuffers(window); 
     glfwPollEvents(); 
      //limit to 100FPS for when vsync is disabled 
     std::chrono::milliseconds dura(10); 
     std::this_thread::sleep_for(dura); 
    } 

    glfwDestroyWindow(window); 
    glfwTerminate(); 
    exit(EXIT_SUCCESS); 
} 

Antwort

7

Ich zögere, dies als eine Antwort zu geben, da ich das nicht wirklich wissen, „Antwort“, aber hoffentlich kann ich etwas Licht auf sie werfen.

Ich habe auch eine nVidia GPU und ich habe das gleiche bemerkt. Meine Vermutung ist, dass der Fahrer im Wesentlichen Spin-Warte:

while(NotTimeToSwapYet()){} 

(oder was auch immer die Phantasie Treiber-Version das aussieht).

process hacker Mit einigen Stack-Traces aus nvoglv32.dll ‚s Thread zu probieren, Das Ding, das etwa 99% der Zeit an der Spitze der Liste ist, ist

KeAcquireSpinLockAtDpcLevel()

, die von Dingen wie

in der Regel stromabwärts

KiCheckForKernelApcDelivery() und EngUnlockDirectDrawSurface()

ich bin nicht gut genug, um in Windows-Treiber-Programmierung vertraut diese schlüssige zu nennen sive, aber es sagt mir auch nicht, dass ich falsch liege.

Und es sieht auch nicht so aus, als würden Sie etwas offensichtlich falsch machen. Es ist meine Erfahrung, dass Swap-Timing in nicht-exklusiven Windows-Anwendungen nur wirklich schmerzhaft ist: Es gibt viel Versuch und Irrtum und eine große Variabilität zwischen verschiedenen Systemen. Soweit ich weiß, gibt es keinen "richtigen" Weg, dies zu tun, der die ganze Zeit gut funktioniert (bitte, jemand sagt mir, dass ich falsch liege!).

In der Vergangenheit konnte ich mich auf vsync verlassen, um die CPU-Auslastung niedrig zu halten (auch wenn es die Dinge etwas weniger reaktionsfähig machte), aber das scheint nicht mehr der Fall zu sein. Ich bin relativ kürzlich von DirectX auf OpenGL umgestiegen, also konnte ich Ihnen nicht sagen, ob es sich um eine kürzlich erfolgte Änderung des nVidia-Treibers handelt oder ob DX und OpenGL nur in Bezug auf vsync unterschiedlich behandelt werden.

+1

Nicht ganz definitiv, aber definitiv hilfreich. Ich fand diesen Beitrag (http://forum.openscenegraph.org/viewtopic.php?t=3653#18283), wo jemand Feedback von den Treiberentwicklern bekam. Entsprechend ihrer Antwort gibt der Fahrer nach. Um das selbst zu testen, habe ich meine 3D-Rendering-Suite meiner Wahl geladen und alle vier CPU-Kerne ausgelastet, während ich das OpenGL-Programm lief. Seine CPU-Auslastung ging von 25% auf 0%. Es scheint, während es einen Kern ausreizt, es nicht wirklich * hog es. –

+0

@Chis_F Danke, das ist gut zu wissen (und etwas ermutigend). Aber mein Hauptanliegen bei der hohen CPU-Auslastung besteht darin, dass Laptops davon abgehalten werden, in den Energiesparmodus zu wechseln. Ich bin mir nicht sicher, ob die Verwendung "künstlich" dort einen Unterschied macht. Vielleicht sind mobile Treiber anders aufgebaut - ich habe keinen zu testen. –

+0

Das ist sicherlich eine Sorge. Nachgeben würde keinen Unterschied in Bezug auf den Stromverbrauch machen, aber vielleicht funktionieren die Treiber für ihre mobilen GPUs anders. –