# Optimal number of work groups for compute shaders

In OpenGL, is there a way to dynamically determine the preferred workgroup size of the underlying hardware? Or at least, to approximate it using some queried metrics?

In OpenCL, you can do this using some implementation defined constants, but so far I wasn't able to find something similar for OpenGL.

• In my experience, 256 threads per group is a good general purpose size for both NV and AMD hardware. It may not be optimal, but many kernels will run pretty well at this size, and it's a good starting place for tweaking. – Nathan Reed Nov 22 '13 at 17:58

In GPGPU, the preferred workgroup size usually is more dependent on the resources used by your compute shader, kernel, etc. and less on the GPU specs. A compute shader will have a maximum number of threads that could run in a multiprocessor based on the resources it uses (since the resources are shared among threads). This concept is one of the cores of compute shader optimization and is the so called Occupancy. In summary, the Occupancy is the ratio of the number of threads that can run in parallel in your compute shader and the maximum number that the GPU supports.

The differences in GPUs related with GPGPU are mainly the number of available multiprocessors and bandwidth. The scheduler of the GPGPU framework (CUDA, DirectCompute, etc.) has the job to assign the workgroups to multiprocessors in a way that compute shaders not depend too much of the GPU specs to scale well (that's the main reason that a boost in the GPU automatically boosts the code performance).

The role of the programmer is to write compute shaders whose workgroups use minimal resource. This is achieved by:

• Minimizing register usage;
• Minimizing shared memory usage;
• Minimizing conditional branches.

For NVidia GPUs you can use the CUDA Occupancy Calculator to check the occupancy based on the number of registers and shared memory used. The compiler outputs this data. Using this tool you can check any workgroup size and see which one gives the best occupancy. You can also use this in DirectCompute since in NVidia cards it is just a "wrapper" for CUDA functionality. Of course there is a lot of experimentation before getting the optimal number.

See this presentation for more details on GPGPU optimizations.

This is really dependent on what you do. there is no optimal number for anything. just on what you do.

I usualy pick something after what im doing. If i will have some shared memory, i try to stay within 32 threads per group. if im doing regular calculation i try to have a bigger group that that so i can get big chunks done rather than small.

If i have a large amount of data, i try to have really big groups so that i dont have to pass the data around to much.

So it all depends on the job!

According to the OpenGL 4.3 spec, you can at least query the maximum number of workgroups and the maximum workgroup size (MAX_COMPUTE_WORK_GROUP_SIZE) as well as the maximum number of invocations. I guess the max workgroup size is a good estimate for best performance.

GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS
GL_MAX_COMPUTE_WORK_GROUP_COUNT
GL_MAX_COMPUTE_WORK_GROUP_SIZE


all to be queried using glGetInteger.