Per presumere un miglioramento della velocità dovuto a qualsiasi forma di multi-elaborazione, è necessario presumere che più attività basate sulla CPU vengano eseguite contemporaneamente su più risorse di elaborazione (generalmente core del processore) oppure che non tutte le attività si basino sull'uso simultaneo di la stessa risorsa - cioè, alcune attività possono dipendere da un sottocomponente del sistema (archiviazione su disco, diciamo) mentre alcune attività dipendono da un altro (ricevere comunicazioni da un dispositivo periferico) e altre ancora possono richiedere l'utilizzo di core del processore.
Il primo scenario viene spesso definito programmazione "parallela". Il secondo scenario è spesso indicato come programmazione "concorrente" o "asincrona", sebbene "concorrente" sia talvolta utilizzato anche per riferirsi al caso in cui si consente semplicemente a un sistema operativo di intercalare l'esecuzione di più attività, indipendentemente dal fatto che tale esecuzione debba posto in serie o se è possibile utilizzare più risorse per ottenere l'esecuzione parallela. In quest'ultimo caso, "concorrente" si riferisce generalmente al modo in cui l'esecuzione è scritta nel programma, piuttosto che dal punto di vista dell'effettiva simultaneità dell'esecuzione del compito.
È molto facile parlare di tutto questo con supposizioni tacite. Ad esempio, alcuni si affrettano a fare affermazioni come "L'I / O asincrono sarà più veloce dell'I / O multithread". Questa affermazione è dubbia per diversi motivi. Innanzitutto, potrebbe essere il caso che un determinato framework I / O asincrono sia implementato precisamente con il multi-threading, nel qual caso sono uno nella stessa cosa e non ha senso dire che un concetto "è più veloce" dell'altro .
In secondo luogo, anche nel caso in cui sia presente un'implementazione a thread singolo di un framework asincrono (come un ciclo di eventi a thread singolo), è comunque necessario fare un'ipotesi su cosa sta facendo quel ciclo. Ad esempio, una cosa sciocca che puoi fare con un ciclo di eventi a thread singolo è richiedere che completi in modo asincrono due diverse attività puramente legate alla CPU. Se lo facessi su una macchina con solo un singolo core idealizzato del processore (ignorando le moderne ottimizzazioni hardware), allora l'esecuzione di questa attività "in modo asincrono" non funzionerebbe in modo diverso rispetto a eseguirla con due thread gestiti in modo indipendente o con un solo processo solitario - - la differenza potrebbe dipendere dal cambio di contesto del thread o dalle ottimizzazioni della pianificazione del sistema operativo, ma se entrambe le attività andranno alla CPU, sarebbe simile in entrambi i casi.
È utile immaginare molti casi insoliti o stupidi in cui potresti imbatterti.
"Asincrono" non deve essere simultaneo, ad esempio proprio come sopra: si eseguono "in modo asincrono" due attività legate alla CPU su una macchina con esattamente un core del processore.
L'esecuzione multi-threaded non deve essere simultanea: si generano due thread su una macchina con un singolo core del processore o si chiedono a due thread di acquisire qualsiasi altro tipo di risorsa scarsa (si immagini, ad esempio, un database di rete che può stabilirne solo uno connessione alla volta). L'esecuzione dei thread potrebbe essere intercalata, tuttavia lo scheduler del sistema operativo lo ritiene opportuno, ma il loro runtime totale non può essere ridotto (e sarà aumentato dal cambio di contesto del thread) su un singolo core (o più in generale, se si generano più thread di quanti ce ne siano core per eseguirli o avere più thread che richiedono una risorsa rispetto a ciò che la risorsa può sostenere). La stessa cosa vale anche per l'elaborazione multipla.
Quindi né l'I / O asincrono né il multi-threading devono offrire alcun miglioramento delle prestazioni in termini di tempo di esecuzione. Possono persino rallentare le cose.
Se si definisce un caso d'uso specifico, tuttavia, come un programma specifico che effettua una chiamata di rete per recuperare i dati da una risorsa connessa alla rete come un database remoto e fa anche alcuni calcoli locali legati alla CPU, è possibile iniziare a ragionare su le differenze di prestazioni tra i due metodi data una particolare ipotesi sull'hardware.
Le domande da porsi: quanti passaggi di calcolo devo eseguire e quanti sistemi di risorse indipendenti ci sono per eseguirli? Esistono sottoinsiemi delle fasi di calcolo che richiedono l'utilizzo di sottocomponenti di sistema indipendenti e possono trarre vantaggio dal farlo contemporaneamente? Quanti core del processore ho e qual è il sovraccarico per l'utilizzo di più processori o thread per completare le attività su core separati?
Se le tue attività si basano in gran parte su sottosistemi indipendenti, una soluzione asincrona potrebbe essere buona. Se il numero di thread necessari per gestirlo fosse elevato, in modo tale che il cambio di contesto diventasse non banale per il sistema operativo, una soluzione asincrona a thread singolo potrebbe essere migliore.
Ogni volta che le attività sono vincolate dalla stessa risorsa (ad es. Più necessità di accedere contemporaneamente alla stessa rete o risorsa locale), il multi-threading probabilmente introdurrà un sovraccarico insoddisfacente, e mentre l'asincronia a thread singolo potrebbe introdurre meno overhead, in tale risorsa- situazione limitata anch'essa non può produrre un'accelerazione. In tal caso, l'unica opzione (se si desidera aumentare la velocità) è rendere disponibili più copie di quella risorsa (ad esempio più core del processore se la risorsa scarsa è la CPU; un database migliore che supporta più connessioni simultanee se la risorsa scarsa è un database con limitazioni di connessione, ecc.).
Un altro modo per dirlo è: consentire al sistema operativo di intercalare l'utilizzo di una singola risorsa per due attività non può essere più veloce che lasciare semplicemente che un'attività utilizzi la risorsa mentre l'altra attende, quindi lasciare che la seconda attività finisca in serie. Inoltre, il costo dello scheduler dell'interleaving significa che in qualsiasi situazione reale crea effettivamente un rallentamento. Non importa se si verifica l'utilizzo interlacciato della CPU, di una risorsa di rete, di una risorsa di memoria, di un dispositivo periferico o di qualsiasi altra risorsa di sistema.