13
$\begingroup$

I am wondering what's the best way to integrate a dynamic loop function in a shader?

First, it seems that dynamic arrays are not possible. So, is it better to create a maximum size array and only fill a part of it or define arrays with predefined sizes?

Then, what's the best way to iterate over this array?

Is it better to use an unrolled loop or a dynamic loop for something between 4 to 128 iterations? I've also seen that it's possible to unroll it to a maximum predefined number of iterations then stop it with a condition such as if (i == myCurrentMaximumIterationNumber).

$\endgroup$
2
  • 2
    $\begingroup$ What are you trying to do with the array and loop? I'm asking because this somehow sounds like an XY Problem to me. Since the best way to use conditions and loops on the GPU is to refrain from using them, maybe there are even better ways instead of using arrays and loops in your case. $\endgroup$
    – Nero
    Commented Mar 8, 2016 at 21:38
  • $\begingroup$ I am implementing a screenspace subsurface scattering effect which currently work. But I have some doubts about the way I use the kernel according to performances. I've choose to do a maximum array size and fill only a part and use a dynamic loop with a dynamic number of iteration which is related to the currently used array content. I think that there are things to do or know when programming shaders according to performances for example. And in my opinion loops is a common performance topic which might follow some rules and maybe "good practices" but I didn't found any good answer about it. $\endgroup$
    – MaT
    Commented Mar 9, 2016 at 7:38

1 Answer 1

7
$\begingroup$

Shader compilers are extremely aggressive about unrolling since early HW often didn't have flow control and the cost on more recent HW can vary. If you have a benchmark you are actively testing against and a range of relevant hardware, then try things to see what happens. Your dynamic loop is more amenable to developer intervention than a static loop - but leaving it to the compiler is still good advice unless you have a benchmark available. With a benchmark, exploration is worthwhile (and fun).

BTW, the biggest loss with a dynamic loop on a GPU is that individual "threads" in a wavefront/warp will finish at different times. The threads that stop later force all the ones that finish early to execute NOPs.

Nested loops should be carefully thought through: I implemented a block based entropy decoder that encoded runs of zeros (for JPEG like compression). The natural implementation was to decode the runs in a tight inner loop - which meant often only one thread was making progress; by flattening the loop and explicitly testing in each thread if it was currently decoding a run or not, I kept all threads active through the fixed length loop (the decoded blocks were all the same size). If the threads were like CPU threads, the change would have been terrible, but on the GPU I was running on, I got a 6 fold increase in performance (which was still terrible - there weren't enough blocks to keep the GPU busy - but it was a proof of concept).

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.