Cos'è il furto di lavoro?

I computer moderni hanno più core di elaborazione. Supponendo che ci sia abbastanza elaborazione in modo che ogni core possa rimanere continuamente occupato. verrà loro assegnata una coda di elementi di lavoro computazionali. O thread da completare dallo scheduler.

Durante l'esecuzione di questi thread, è possibile generare nuovi thread o elementi di lavoro. Si tratta di thread separati che possono essere elaborati contemporaneamente. Potrebbero dover inviare i risultati ai programmi di deposizione delle uova o rimanere completamente separati indefinitamente. In genere, questi thread figlio vengono assegnati allo stesso core di elaborazione del padre.

Tutto ciò presuppone che tutti i core siano tenuti occupati. Ciò accadrà se nessun thread termina o nuovi thread vengono generati alla stessa velocità o più velocemente rispetto alla fine dei thread esistenti. Nel mondo reale, tuttavia, il carico di lavoro a lungo termine è raramente così semplice, specialmente nei dispositivi di elaborazione degli utenti finali. Alla fine, un core di elaborazione completerà probabilmente tutte le attività assegnate. Quando ciò accade, invece di rimanere inattivo e sprecare potenziali prestazioni, controlla invece le code di lavoro degli altri core di elaborazione e ruba loro un elemento di lavoro.

Vantaggi e svantaggi

Il furto di lavoro significa che un core di elaborazione inattivo cercherà attivamente il lavoro per il completamento. Ciò impedisce a una frazione potenzialmente ampia del processore complessivo di rimanere inattiva, il che è utile. Tuttavia, il furto di lavoro può comportare dei costi. Ad esempio, il nuovo core di elaborazione dovrà probabilmente caricare tutti i dati rilevanti nella sua memoria cache.

Questo può richiedere del tempo, soprattutto se deve essere richiesto dalla RAM di sistema anziché essere servito da un livello di cache condiviso. È possibile che il processore originale sarebbe stato in grado di riprendere quell'elemento di lavoro in quel lasso di tempo, portando a un'esecuzione complessiva più rapida. Ciò può verificarsi anche se il nucleo di elaborazione da cui è stato rubato l'elemento di lavoro non ha mai iniziato a elaborarlo. Alcuni valori memorizzati nella cache possono essere identici tra i thread padre e figlio.

Implementazioni

Diversi linguaggi di programmazione hanno tempi di esecuzione in grado di pianificare il lavoro direttamente su processori dedicati. Ad esempio, il linguaggio di programmazione Cilk, il runtime Rust Tokio e la libreria .Net Task Parallel possono farlo. In alternativa, il sistema operativo può essere incaricato della pianificazione del tempo effettivo del processore. Con il programma che aggiunge semplicemente attività a un pool di "thread di lavoro", che sono a loro volta pianificati dal sistema operativo.

Ciò accade nei sistemi in cui il programma non ha un accesso diretto dedicato ai core di elaborazione ma deve condividere l'accesso con altri processi. È necessario prestare particolare attenzione in questo scenario per garantire che un thread non venga rubato ripetutamente mentre rimane inattivo.

Esistono vari approcci su come selezionare gli oggetti di lavoro per essere rubati. Nel concetto originale, l'approccio era quello di scegliere un altro nucleo casuale. Se aveva uno o più elementi di lavoro in coda, prendi l'ultimo. A seconda della preferenza per il fatto che un processo figlio venga eseguito immediatamente dal processore di origine. Oppure, se viene inviato alla coda del processore e il processo padre continua a essere eseguito, il thread padre o figlio verrà rubato.

Tutto può essere riassunto come Work Stealing, una tecnica di bilanciamento del carico che assicura che il carico di parole sia distribuito uniformemente tra i processori disponibili. In questo modo, tutti i processori stanno facendo qualcosa per aiutare.

Conclusione

Il furto di lavoro è un processo che avviene automaticamente nelle CPU multicore. Ogni core ha una coda di attività da eseguire. Quando un processore completa le sue attività, ruba un'altra attività dalla coda di un altro core di elaborazione. Questo aiuta a impedire al processore di avere alcuni core inattivi mentre altri hanno ancora una coda di attività da eseguire.