7
\$\begingroup\$

I'm trying to use an uniform array of matrices in my compute shader. However, it's really slow. I've narrowed it down to this lines of code:

uniform mat4 someMatrixArray[64]; 
...
vec4 result = vec4(0);
for (int i = 0; i < 2048; i++) {
    result += someMatrixArray[i%64][0] * 0.01;
}

When not accessing someMatrixArray I get 700+ fps. When accessing it, I have 10 fps. Anybody has an idea what could cause this? Could it be a driver issue?

I already tried to unroll the loops (via #pragma optionNV (unroll all)) but that didn't help. I'm using a GTX670 with the latest drivers on windows 7.

Edit:

The generated assembly for the inner loop is:

MAD.F R0.xyz, c[196], {0.0099999998, 0, 0, 0}.x, R0;
\$\endgroup\$
7
  • \$\begingroup\$ Seems like the value of result can be determined statically without needing to be evaluated in the shader. Why not calculate it on the CPU and pass in the final value of result to the shader as a uniform? \$\endgroup\$ Jun 26 '14 at 23:21
  • \$\begingroup\$ This is only my test case :) my actual code looks different (I'm trying to implement tiled deferred shading) \$\endgroup\$
    – tobspr
    Jun 27 '14 at 5:21
  • \$\begingroup\$ try integer division instead of float multiplication and see what changes you get: result += someMatrixArray[i%64][0] / 100; \$\endgroup\$ Jul 10 '14 at 15:33
  • 1
    \$\begingroup\$ @Blue That would be interesting if that did indeed help. ARB instruction set doesn't appear to have a combined divide/add like it does for multiply/add. In theory it would either split it into two instructions, or convert it to multiplication as a compiler optimization. Though I have seen crazier things, so it certainly wouldn't be out of the realm of possibility. Instruction set is here. renderguild.com/gpuguide.pdf \$\endgroup\$
    – Evan
    Aug 11 '14 at 14:04
  • 1
    \$\begingroup\$ If I were you, I would use something such as developer.nvidia.com/nvidia-visual-profiler to profile shader runs to identify whether your bottleneck is reading from that uniform variable location, or if it is simply the number of clock cycles spent looping. Since every loop is boiling down to a single MAD instruction that reads and writes out to the same register, chances are good it is reading from c[index], or simply too many iterations. \$\endgroup\$
    – Evan
    Aug 11 '14 at 14:10
1
\$\begingroup\$

Yes, accessing memory can always be substantially slower than not accessing memory. Particularly in a for loop that's executing 2000 times inside a shader.

I don't think there's anything particularly surprising, here -- breaking the task up into smaller steps that can each be executed in parallel and using smaller amounts of data should definitely help.

\$\endgroup\$
1
  • \$\begingroup\$ Yes, that's what I figured out, too :) I splitted it into multiple passes, and now it works fine \$\endgroup\$
    – tobspr
    Aug 16 '14 at 8:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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