Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 11

Thread: Performance: alternative for if ( ... ) { }

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Nov 2011
    Posts
    11

    Performance: alternative for if ( ... ) { }

    Hi there,

    some years ago I read that if-statements should be avoided in shader source to get better performance.

    Code :
    if (UniformTwoSided && Dot < 0.0)
    {
      Dot *= Flip;
      FragNormal *= Flip;
    }

    Is that still the case? And if yes, is that a faster alternative for the code above?
    Code :
    float Flip = UniformTwoSidedFlipVec[int(step(0.0, Dot))];
    Dot *= Flip;
    FragNormal *= Flip;

    Code :
    static const float FlipVec[2][2] = { {1.0f, 1.0f}, {-1.0f, 1.0f} };
    glUniform2fv(FlipVecLocation, 1, FlipVec[(int) TwoSided]);


    Basically the second code uses a vector and some client side switch
    to achieve the same result but makes the code less readable.
    Not even sure if it makes it faster so your comments are really welcome!

    Thanks!
    ++i--;

  2. #2
    Senior Member OpenGL Pro Ilian Dinev's Avatar
    Join Date
    Jan 2008
    Location
    Watford, UK
    Posts
    1,261
    The compilers will look at the size and complexity of the code that's in if/else blocks. The "Dot *= Flip; FragNormal *= Flip; " part, in this case. If it's small/calculations-only, then predicated instructions will be generated (much like instructions in ARM cpus). Otherwise, dynamic branching - which will halve your performance per jump if there's no coherence. In some cases you want early-return from a shader, there you're almost always at a win.

    If you try to avoid if-statements like the plague, you may end-up adding 5-10 arithmetic instructions to do what 2 predicated instructions can do.

  3. #3
    Member Regular Contributor
    Join Date
    Jan 2012
    Location
    Germany
    Posts
    302
    Some early programmable GPUs evaluated both, the if and the else part of a switch and ignored one result. In that time each if slowed you down. Nowadays the GPUs jump if the condition is false - if it is false for all processed fragments/vertices (that's for example batches of 32 on NVidia GPUs). If some elements take the if and some dont, all cores will evaluate the same path (== both pathes) or wait. So for fragments shaders the worst case would be:

    Code :
    if (gl_FragCoord.x % 2 == 1) {
    ...
    } else {
    ...
    }

    While something like this won't get you into trouble:

    Code :
    if (uniformValue == 1) {
    ...
    } else {
    ...
    }

    It all boils down to the question, does your condition evaluate differently for elements that are (likely) processed together?

  4. #4
    Advanced Member Frequent Contributor
    Join Date
    Apr 2010
    Location
    Germany
    Posts
    895
    Edit: Removed due to stating the exact same thing as menzel. That's what I get for not reading carfully enough.
    Last edited by thokra; 05-29-2012 at 01:31 AM.

  5. #5
    Member Regular Contributor
    Join Date
    Jan 2012
    Location
    Germany
    Posts
    302
    thokra: you're right but that's also what i said: older GPUs executed both pathes. always. Newer GPUs execute both pathes only if some of the elements (vertices/fragments) of one batch use different branches (and this number can be as high as 32 on some NVidias or even higher).

  6. #6
    Member Regular Contributor
    Join Date
    Apr 2009
    Posts
    258
    Quote Originally Posted by menzel View Post
    While something like this won't get you into trouble:

    Code :
    if (uniformValue == 1) {
    ...
    } else {
    ...
    }
    If this is your usecase, you could have a look at subroutines, which in theory were introduced specifically for such usecase (different codepaths depending on uniform value).
    Dont have much idea as to what performance profile of the feature is though.

  7. #7
    Junior Member Newbie
    Join Date
    Nov 2011
    Posts
    11
    Thank you all for the comments!

    Since I have only two lines in the if-block it might be possible that these predicated instructions are used.

    Are if-statements without an else-block generally less "dangerous" regarding performance?
    ++i--;

  8. #8
    Advanced Member Frequent Contributor
    Join Date
    Dec 2007
    Location
    Hungary
    Posts
    941
    Quote Originally Posted by RealtimeSlave View Post
    Are if-statements without an else-block generally less "dangerous" regarding performance?
    Well, in many cases yes. Think about it, if you use predicated instructions, you have probably less predicated instructions if you don't have an else branch. If actual branching is used, you get the worst case performance of the block behind the "if" being executed always, even if only one thread took that path, instead of having to execute two branches (the "if" and the "else") in case of divergence.

    However, this all depends on how large is your "if" and "else" block and how diverging is your branching. It's not the "else" itself that could cost you much performance.
    Disclaimer: This is my personal profile. Whatever I write here is my personal opinion and none of my statements or speculations are anyhow related to my employer and as such should not be treated as accurate or valid and in no case should those be considered to represent the opinions of my employer.
    Technical Blog: http://www.rastergrid.com/blog/

  9. #9
    Junior Member Newbie
    Join Date
    Nov 2011
    Posts
    11
    Got it, thanks!
    ++i--;

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •