Xbox One Occupancy Quick Reference

Martin Fuller, Xbox Advanced Technology Group

Published May 13th 2016

In this topic

Overview of a compute unit

Local data store

Cheat sheets

Bank conflicts

Summary

Related articles

Overview of a compute unit

The Xbox One GPU is comprised of two shader engines, each with six compute units (CUs).

Because the fastest instruction takes a SIMD four cycles to complete, and there are four SIMDs per CU, each CU can issue a vector ALU operation per cycle. Waves per SIMD is known as occupancy. Typically, engineers should aim for an occupancy of at least 3, preferably 4 or greater.

Local data store

When a shader uses LDS, all waves in a threadgroup must execute on the same CU. Although each CU has 64 KB of LDS, we prohibit allocating more than 32 KB per threadgroup.

In the event that there is just one wave per threadgroup (<= 64 threads issued) and that group requires 32 KB of LDS, the CU is only able to run two waves concurrently, meaning that half the SIMDs are unused. This is a catastrophic performance issue.

Cheat sheets

Max occupancy per SIMD Max instructions per clock Max SGPRs
(align 8)
Max VGPRs
(align 4)
1 1 104 256
2 2 104 128
3 3 104 84
4 4 104 64
5 5 96 48
6 5 80 40
7 5 72 36
8 5 64 32
9 5 56 28
10 5 48 24

LDS per threadgroup (KB, aligned to 256 bytes)

Max occupancy per SIMD Threadgroup
= 1 wave
Threadgroup
= 2 waves
Threadgroup
= 4 waves
1 16 32 -
2 8 16 32
3 5.25 10.5 21.25
4 4 8 16
5 3 6.25 12.75
6 2.5 5.25 10.5
7 2.25 4.5 9
8 2 4 8
9 1.75 3.5 7
10 1.5 3 6.25

The maximum LDS allocation in bytes for each occupancy tipping point is given by:

  floor(((65536 / (maxWavesPerSIMD * 4)) * ThreadsPerGroup) / 256) * 256

Bank conflicts

LDS is arranged into 32 banks of 2 KB each. Each bank has a 32-bit wide bus, providing a maximum bandwidth of 128 bytes per cycle per CU. An LDS instruction is split into two operations, one for the low 32 threads and one for the high 32. For conflicts, we only need to consider one of these 32-bit wide accesses.

Of the 16-bit address, the most significant 9 bits select the address within the bank, the next 5 bits select the bank, and the least significant 2 bits select the byte within the 32-bit wide address. (However, currently we only expose 32-bit access.)

A bank conflict is generated when:

In the case of a bank conflict, the memory operation will be N times slower, where N is the highest number of threads accessing the same bank. For example:

The advice is therefore to avoid writing to LDS with strides that are a power of 2 .

There is no penalty if threads in the high 32 threads access the same banks as threads in the low 32 threads.

  1. Greater than zero of course

Summary

This paper provides a quick reference that you can use when optimizing for occupancy. While register allocation is relatively straight forward, effective LDS optimization is dependent not only on occupancy, but also on ensuring that waves do not generate bank conflicts.

Related articles