GLSL: Loop-Unrolling und IF-Statements - mehr Performance



  • Hallo allerseits,
    also zu allererst wollte ich sagen, dass ich mich auch auf ältere Hardware beziehe..
    In GLSL werden Schleifen ja abgerollt, und alle Zweige eines if berechnet und ggf. verworfen, soviel ich weiß.
    Aber wie ist das mit "break" im Loop?
    Also z.B. "if(xyz) break;"
    oder in Funktionen "if(xyz) return;"

    Weiß jemand, ob da trotzdem alles, was "darunter" geschieht noch berechnet wird??
    Oder kennt jemand Hausnummern, ab welchem Jahr ca. Hardware richtige Loops und IFs unterstützt?


  • Mod

    wenn ich mich recht entsinne koennen grakas seit ca 2006 das. ich glaube das fing mit NV40 (ich gluabe geforce 6800) und R520 (Radeon x1800 an).

    ein break ist nicht anders als ein "else". du kannst

    for(int i=0;i<n;i++)
    {
     if(foo(i))
       break;
    }
    

    in sowas umformen

    bool running=true;
    for(int i=0;i<n;i++)
    {
     if(running)
       running=foo(i);
    }
    

    was die compiler im einzelnen machen kannst du bei glsl schwer kontrollieren. in manchen faellen hab ich bei nvidia treibern eine warnung bekommen wenn ein loop ueber 4096 iterationen hatte, dass "unrolling" deswegen deaktiviert wurde. vorher wurde es also, wie du sagst, "abgerollt", obwohl mein loop-body recht gross war.



  • Ah hat sich doch noch jemand gefunden.. 😃
    Danke! Also 2006 sollte lange genug her sein, kurz gesagt.

    Nur zur Sicherheit; das gilt dann auch für ein

    if(..){ return ding; }
    return dong;

    , oder?


  • Mod

    if(..){ return ding; } 
    return dong;
    [cpp]
    wird zu
    [cpp]
    if(..){ dong=ding;} 
    return dong;
    

    auch in einem loop (nur wird da noch ein 'break;' reinemuliert.



  • Bin jetzt doch nochmal kurz verwirrt..

    Also es wird nicht zu:

    if(..){ dong=ding; }
    else{ return dong; }
    

    ?

    Besser ein konkretes Bsp.. Ich frage mich, ob sich ein "early-out" lohnt?! Also

    bool quit = false;
    if(...) quit = true;
    if(quit) return 0.;
    float asd = f(..);
    return asd;
    

    Bzw.

    bool quit = false;
    if(...) quit = true;
    float asd;
    if(quit) asd = 0.;
    else asd = f(..);
    return asd;
    

    ..was eig. identisch sein sollte..

    Also spare ich mir evtl. das f(...), oder wird das in jedem Fall berechnet, was dann bedeuten würde, dass die ganze quit-Geschichte überflüssig/eine Verschlimmbesserung wäre?!

    Oder ist es so, dass dadurch ältere Hardware noch langsamer mache, neue dafür aber noch schneller?? 😃


  • Mod

    du darfst annehmen, dass der code richtig funktionieren wird.
    du darfst _nicht_ annehmen, dass der code schneller/langsammer wird, um das zu wissen, musst du den konkreten fall profileren.


Anmelden zum Antworten