A display controller must fetch a line of pixels every few microseconds, or the screen tears. A GPU sharing the same memory will happily use all the bandwidth it can get. Round-robin gives them equal turns, which is fair and wrong: the GPU's long bursts and deep queues still push the display's reads past their deadline. The display does not need more bandwidth than the GPU. It needs a promise.
How does a shared fabric keep different promises to different kinds of traffic?
The obvious answer is priority: give the display the highest priority everywhere. It helps at arbiters, but the display's reads still wait in queues full of GPU requests that were accepted earlier (lesson 8.4), behind GPU bursts already in progress (lesson 8.5), and in memory controllers optimising for GPU efficiency (lesson 6.10). And if the display were ever given unlimited priority and misbehaved, it would starve everything else. Quality of service is a combination of mechanisms, each closing one of these gaps.
Mechanism | What it does | Closes the gap of |
|---|---|---|
Traffic classes | Label each transaction with what kind of traffic it is (real-time, latency-sensitive, bulk) | Agents along the path not knowing what matters |
Priority | Arbiters and schedulers prefer higher classes | Losing arbitration to bulk traffic |
Bandwidth regulation | Limit each source's rate and burst (token buckets, lesson 4.10) | A high-priority source starving others, and bulk sources flooding queues |
Reserved resources | Queue slots, buffers or virtual channels that only a class may use | Waiting behind other traffic already queued |
Illustrative numbers:
Display needs: 2 GB/s, and each read back within 2 us (its line buffer covers 2 us)
GPU regulated to: 20 GB/s average, bursts of at most 32 requests
Worst wait for a display read at the memory port:
in-progress GPU burst (capped at 16 beats) ~16 cycles
GPU requests ahead in the shared queue 0 (display uses its reserved queue)
memory controller latency at expected load ~600 ns
Result: well under 2 us; without the reserved queue, up to 32 queued GPU requests could add several microsecondsProtocol | QoS fields and mechanisms |
|---|---|
AXI4 | AxQOS: a 4-bit priority value on each transaction, used by interconnects and memory controllers; regulators at ports enforce rates. |
PCI Express | Traffic classes (3 bits) mapped onto virtual channels with separate buffers and credits, so classes do not share queues. |
Network-on-chip | Separate virtual channels per class, priority arbitration with ageing, and rate regulation at injection points. |
Priority without regulation: a real-time source with a bug (illustrative) issued requests continuously at top priority and starved the whole system. High priority must come with a rate limit.
Priority without reserved resources: the display had top priority but its reads still waited behind 64 GPU requests already in the memory controller's queue. A few reserved slots fixed it.
Classes lost at a bridge: a bridge that dropped AxQOS turned every display read into ordinary traffic beyond it (lesson 5.17).
It can wait behind requests already queued ahead of it, behind a burst in progress, or behind a held resource; priority only helps at arbitration.
A bound on how many GPU requests can arrive in a burst and how fast they come on average, which bounds queue occupancy and the display's wait.
QoS combines traffic classes, priority, bandwidth regulation and reserved resources.
Priority helps at arbiters; reservations help in queues; regulation bounds everyone, including the high-priority source.
Write QoS as per-class promises and name the mechanism that keeps each one at every shared resource.