Il weighted round robin (WRR, in italiano round robin pesato) è uno scheduler di rete per flussi di dati, utilizzato anche per lo scheduling dei processi.
Il weighted round robin è una generalizzazione della schedulazione round robin e serve un insieme di code o di task. Mentre il round-robin scorre ciclicamente le code o i task e concede un'opportunità di servizio per ciclo, il weighted round robin ne offre a ciascuno un numero fisso, specificato dal peso configurato, che serve a influenzare la quota di capacità ricevuta da ogni coda o task. Nelle reti di calcolatori, un'opportunità di servizio corrisponde all'emissione di un pacchetto, se la coda selezionata non è vuota.
Se tutti i pacchetti hanno la stessa dimensione, il WRR è l'approssimazione più semplice del generalized processor sharing (GPS). Esistono diverse varianti del WRR. Le principali sono il WRR classico e il WRR interlacciato.
Di seguito, il WRR è presentato come scheduler di rete. Può essere utilizzato in modo analogo anche per lo scheduling dei task.
Uno scheduler di rete WRR ha code di ingresso, . A ogni coda è associato , un intero positivo detto peso. Lo scheduler WRR ha un comportamento ciclico: in ogni ciclo, ciascuna coda dispone di opportunità di emissione.
I diversi algoritmi WRR differiscono per il modo in cui queste opportunità sono distribuite all'interno del ciclo.
Nel WRR classico lo scheduler scorre ciclicamente le code. Quando una coda viene selezionata, lo scheduler invia pacchetti fino all'emissione del -esimo pacchetto o fino allo svuotamento della coda.
Costanti e variabili:
const N // numero di code
const weight[1..N] // peso di ciascuna coda
queues[1..N] // code
i // indice della coda
c // contatore dei pacchetti
Istruzioni:
while true do
for i in 1 .. N do
c := 0
while (not queue[i].empty) and (c<weight[i]) do
send(queue[i].head())
queue[i].dequeue()
c:= c+1 |
Sia il peso massimo. Nell'IWRR (interleaved WRR), ogni ciclo è suddiviso in turni. Una coda con peso può emettere un pacchetto al turno solo se .
Costanti e variabili:
const N // numero di code
const weight[1..N] // peso di ciascuna coda
const w_max
queues[1..N] // code
i // indice della coda
r // contatore dei turni
Istruzioni:
while true do
for r in 1 .. w_max do
for i in 1 .. N do
if (not queue[i].empty) and (weight[i] >= r) then
send(queue[i].head())
queue[i].dequeue() |

Si consideri un sistema con tre code e rispettivi pesi . Si supponga che nella prima coda vi siano 7 pacchetti, A,B,C,D,E,F,G, 3 nella seconda, U,V,W, e 2 nella terza, X,Y. Si assuma che non arrivino altri pacchetti.
Con il WRR classico, nel primo ciclo lo scheduler seleziona dapprima e trasmette i cinque pacchetti in testa alla coda, A,B,C,D,E (poiché ); poi seleziona la seconda coda, , e trasmette i due pacchetti in testa, U,V (poiché ); infine seleziona la terza coda, che ha peso 3 ma contiene solo due pacchetti, e trasmette quindi X,Y. Subito dopo la fine della trasmissione di Y inizia il secondo ciclo, nel quale vengono trasmessi F,G da , seguiti da W da .
Con il WRR interlacciato, il primo ciclo è suddiviso in 5 turni (poiché ). Nel primo turno (r=1) viene inviato un pacchetto da ciascuna coda (A,U,X); nel secondo (r=2) viene inviato un altro pacchetto da ciascuna coda (B,V,Y); nel terzo (r=3) solo le code possono inviare un pacchetto (, e ), ma poiché è vuota viene inviato solo C da ; nel quarto e nel quinto turno vengono inviati solo D,E da . Inizia poi il secondo ciclo, nel quale vengono inviati F,W,G.
Come il round-robin, lo scheduling weighted round robin è semplice, facile da implementare, work-conserving (non lascia mai inattiva la risorsa se ci sono richieste in attesa) e privo di starvation.
Nello scheduling dei pacchetti, se tutti i pacchetti hanno la stessa dimensione, WRR e IWRR costituiscono un'approssimazione del generalized processor sharing: una coda riceverà, nel lungo periodo, una quota di banda pari a (se tutte le code sono attive), mentre il GPS serve quantità infinitesimali di dati da ciascuna coda non vuota e garantisce tale quota su qualsiasi intervallo.
Se le code contengono pacchetti di lunghezza variabile, la quota di banda ricevuta da ciascuna coda dipende non solo dai pesi ma anche dalle dimensioni dei pacchetti.
Se per ogni coda è nota la dimensione media dei pacchetti , ciascuna coda riceverà nel lungo periodo una quota di banda pari a . Se l'obiettivo è assegnare a ogni coda una porzione della capacità del collegamento (con ), si può porre .
Poiché l'IWRR produce burst per classe più piccoli rispetto al WRR, ne derivano ritardi (nel caso peggiore) inferiori.
Il WRR per lo scheduling dei pacchetti di rete fu proposto per la prima volta da Katevenis, Sidiropoulos e Courcoubetis nel 1991, specificamente per lo scheduling nelle reti ATM, che utilizzano pacchetti di dimensione fissa (celle). Il limite principale dell'accodamento weighted round robin è che fornisce la corretta percentuale di banda a ciascuna classe di servizio solo se tutti i pacchetti in tutte le code hanno la stessa dimensione, oppure se la dimensione media dei pacchetti è nota in anticipo. Nel caso più generale delle reti IP, con pacchetti di dimensione variabile, per approssimare il GPS i pesi devono essere regolati in base alla dimensione dei pacchetti. Ciò richiede una stima della dimensione media dei pacchetti, il che rende difficile ottenere in pratica una buona approssimazione del GPS con il WRR.
Il deficit round robin è una variante successiva del WRR che ottiene una migliore approssimazione del GPS senza dover conoscere in anticipo la dimensione media dei pacchetti di ciascuna connessione. Sono state inoltre introdotte tecniche di scheduling più efficaci, che superano i limiti sopra descritti (ad esempio il weighted fair queuing).
Il weighted round robin è stato adottato da diversi sistemi operativi real-time (RTOS) come strategia di scheduling dei task, in cui i pesi dei task determinano la quota di tempo di CPU assegnata a ciascun thread.
Tra gli esempi più noti figura SuperTinyKernel RTOS, un RTOS bare-metal in C++ per sistemi embedded, che implementa una strategia Smooth Weighted Round Robin (SWRR). L'SWRR è una variante migliorata del WRR classico che distribuisce il tempo di CPU in proporzione ai pesi dei task evitando deliberatamente i burst di esecuzione: i task con peso elevato non monopolizzano il processore in un singolo ciclo di scheduling, ma i loro quanti di tempo aggiuntivi vengono distribuiti uniformemente lungo il ciclo. Ne risultano un utilizzo della CPU più uniforme e un minore jitter di scheduling rispetto al WRR classico, al prezzo di un calcolo di scheduling moderatamente più complesso a ogni cambio di contesto.