Condividi tramite


Confronto tra runtime di concorrenza e altri modelli di concorrenza

In questo documento vengono descritte le differenze tra le funzionalità e i modelli di programmazione del runtime di concorrenza e quelli di altre tecnologie. È importante poter confrontare i vantaggi del runtime di concorrenza con quelli di altri modelli di programmazione per poter scegliere la tecnologia che meglio soddisfa i requisiti dell'applicazione in uso.

Se attualmente si utilizza un altro modello di programmazione, ad esempio il pool di thread di Windows oppure OpenMP, vi sono casi in cui può essere appropriato eseguire la migrazione al runtime di concorrenza. Ad esempio, nell'argomento Migrazione da OpenMP al runtime di concorrenza viene descritto quando può essere appropriato effettuare la migrazione da OpenMP al runtime di concorrenza. Se tuttavia si ritiene che le prestazioni dell'applicazione e il supporto di debug corrente siano soddisfacenti, la migrazione non è necessaria.

È possibile utilizzare le funzionalità e i vantaggi della produttività del runtime di concorrenza come completamento dell'applicazione esistente che utilizza un altro modello di concorrenza. Il runtime di concorrenza non può garantire il bilanciamento del carico quando più utilità di pianificazione delle attività competono per le stesse risorse di elaborazione. Nei casi in cui i carichi di lavoro non si sovrappongono, questo effetto è tuttavia minimo.

Sezioni

  • Confronto tra la pianificazione di tipo preemptive e la pianificazione cooperativa

  • Confronto tra il runtime di concorrenza e l'API Windows

  • Confronto tra il runtime di concorrenza e OpenMP

Confronto tra la pianificazione di tipo preemptive e la pianificazione cooperativa

I modelli di pianificazione di tipo preemptive e cooperativa rappresentano due modalità comuni che consentono a più attività di condividere le risorse di elaborazione come, ad esempio, processori o thread di hardware.

Pianificazione di tipo preemptive e cooperativa

La pianificazione di tipo preemptive è un meccanismo round robin basato sulle priorità in base al quale a ogni attività viene concesso l'accesso esclusivo a una risorsa di elaborazione per un periodo di tempo specificato, per poi passare a un'altra attività. La pianificazione di tipo preemptive è comune nei sistemi operativi multitasking come Windows. La pianificazione cooperativa è un meccanismo in base al quale a ogni attività viene concesso l'accesso esclusivo a una risorsa di elaborazione finché l'attività non viene completata o finché l'attività non restituisce l'accesso alla risorsa. Il runtime di concorrenza utilizza la pianificazione cooperativa con l'utilità di pianificazione di tipo preemptive del sistema operativo per ottenere il massimo utilizzo delle risorse di elaborazione.

Differenze tra le utilità di pianificazione di tipo preemptive e cooperativa

Le utilità di pianificazione di tipo preemptive cercano di concedere a più thread lo stesso accesso alle risorse di elaborazione per garantire l'avanzamento di ogni thread. Nei computer che dispongono di molte risorse di elaborazione risulta meno problematico garantire lo stesso accesso, ma più problematico garantire un utilizzo efficiente delle risorse.

Per un'utilità di pianificazione di tipo preemptive in modalità kernel è necessario che il codice dell'applicazione si basi sul sistema operativo per prendere decisioni di pianificazione, mentre un'utilità di pianificazione cooperativa in modalità utente consente al codice dell'applicazione di prendere decisioni di pianificazione autonomamente. Poiché la pianificazione cooperativa consente all'applicazione di prendere molte decisioni di pianificazione, riduce di gran lunga l'overhead associato alla sincronizzazione in modalità kernel. Una pianificazione cooperativa rinvia in genere le decisioni di pianificazione al kernel del sistema operativo quando non sono disponibili altre attività da pianificare. Un'utilità di pianificazione cooperativa rinvia inoltre all'utilità di pianificazione del sistema operativo quando un'operazione di blocco viene comunicata al kernel ma non all'utilità di pianificazione in modalità utente. Nei sistemi operativi che supportano thread pianificabili in modalità utente, l'utilità di pianificazione del runtime di concorrenza converte le operazioni di blocco in operazioni di blocco cooperative.

Pianificazione cooperativa ed efficienza

Per un'utilità di pianificazione di tipo preemptive, tutte le attività con lo stesso livello di priorità sono uguali. Un'utilità di pianificazione di tipo preemptive pianifica in genere i thread nell'ordine in cui vengono creati. Inoltre, un'utilità di pianificazione di tipo preemptive assegna a ogni thread una porzione di tempo in modo round robin, in base alla priorità del thread. Sebbene questo meccanismo sia basato su criteri di equità, ovvero sull'avanzamento di ogni thread, comporta un notevole impegno in termini di efficienza. Per molti algoritmi con calcoli complessi, ad esempio, l'equità non è necessaria, mentre è importante che le attività correlate vengano completate nel minor tempo totale. La pianificazione cooperativa consente a un'applicazione di pianificare il lavoro in modo più efficace. Si consideri, ad esempio, un'applicazione con molti thread. La pianificazione di thread che non condividono risorse per l'esecuzione simultanea può ridurre l'overhead di sincronizzazione incrementando l'efficienza. Un altro modo efficiente di pianificare le attività consiste nell'eseguire pipeline di attività, dove ogni attività agisce sull'output di quella precedente, sullo stesso processore in modo che l'input di ogni fase della pipeline sia già caricato nella cache di memoria.

Utilizzo congiunto di pianificazione di tipo preemptive e cooperativa

La pianificazione cooperativa non risolve tutti i problemi di pianificazione. Ad esempio, le attività che non passano equamente ad altre attività possono utilizzare tutte le risorse di elaborazione disponibili e impedire l'avanzamento di altre attività. Il runtime di concorrenza utilizza i vantaggi dell'efficienza della pianificazione cooperativa per integrare le garanzie di equità della pianificazione di tipo preemptive. Per impostazione predefinita, il runtime di concorrenza fornisce un'utilità di pianificazione cooperativa che utilizza un algoritmo di acquisizione del lavoro per distribuire il lavoro tra le risorse di elaborazione in modo efficiente. Tuttavia, l'utilità di pianificazione del runtime di concorrenza si basa anche sull'utilità di pianificazione di tipo preemptive del sistema operativo per distribuire equamente le risorse tra le applicazioni. È inoltre possibile creare utilità di pianificazione personalizzate e criteri dell'utilità di pianificazione nelle applicazioni per produrre un controllo accurato sull'esecuzione dei thread.

[vai all'inizio]

Confronto tra il runtime di concorrenza e l'API Windows

L'API di Microsoft Windows, definita in genere API Windows, e precedentemente nota come Win32, fornisce un modello di programmazione che consente la concorrenza nelle applicazioni. Il runtime di concorrenza si basa sull'API Windows per fornire modelli di programmazione aggiuntivi che non sono resi disponibili dal sistema operativo sottostante.

Il runtime di concorrenza si basa sul modello di thread dell'API Windows per eseguire attività in parallelo. Utilizza inoltre la gestione della memoria e i meccanismi di archiviazione locale del thread dell'API Windows. In Windows 7 e Windows Server 2008 R2 utilizza il supporto dell'API Windows per i computer e i thread pianificabili dall'utente con oltre 64 thread di hardware. Il runtime di concorrenza estende il modello dell'API Windows fornendo un'utilità di pianificazione cooperativa e un algoritmo di acquisizione del lavoro per massimizzare l'utilizzo delle risorse di elaborazione e consentendo più istanze dell'utilità di pianificazione simultanee.

Per ulteriori informazioni sull'API Windows, vedere Cenni preliminari sull'API Windows.

Linguaggi di programmazione

L'API Windows utilizza il linguaggio di programmazione C per esporre il modello di programmazione. Il runtime di concorrenza fornisce un'interfaccia di programmazione in C++ che sfrutta i vantaggi delle funzionalità più recenti del linguaggio C++. Le funzioni lambda forniscono, ad esempio, un meccanismo sintetico indipendente dai tipi per la definizione di funzioni lavoro parallele. Per ulteriori informazioni sulle funzionalità di C++ più recenti utilizzate dal runtime di concorrenza, vedere Cenni preliminari sul runtime di concorrenza.

Thread e pool di thread

Il meccanismo di concorrenza centrale nell'API Windows è il thread. Per creare i thread viene in genere utilizzata la funzione CreateThread. Sebbene la creazione e l'utilizzo dei thread siano relativamente semplici, il sistema operativo alloca una quantità significativa di tempo e di altre risorse per la relativa gestione. Inoltre, sebbene per ogni thread sia garantito lo stesso tempo di esecuzione di un altro thread con lo stesso livello di priorità, l'overhead associato richiede la creazione di attività sufficientemente grandi. Per le attività più piccole o più precise, l'overhead associato alla concorrenza può compensare il vantaggio dell'esecuzione delle attività in parallelo.

I pool di thread rappresentano un modo per ridurre il costo di gestione dei thread. I pool di thread personalizzati e l'implementazione di pool di thread fornita dall'API Windows consentono entrambi l'esecuzione efficiente in parallelo di piccoli elementi di lavoro. Il pool di thread di Windows gestisce gli elementi di lavoro in una coda FIFO (First-In, First-Out). Ogni elemento di lavoro viene avviato nell'ordine in cui è stato aggiunto nel pool.

Il runtime di concorrenza implementa un algoritmo di acquisizione del lavoro per estendere il meccanismo di pianificazione FIFO. L'algoritmo sposta le attività che non sono ancora state avviate nei thread che hanno esaurito gli elementi di lavoro. Sebbene l'algoritmo di acquisizione del lavoro possa bilanciare i carichi di lavoro, può anche riordinare gli elementi di lavoro. Questo processo di riordinamento può comportare l'avvio di un elemento di lavoro in un ordine diverso da quello con cui è stato inviato. Ciò si rivela utile con gli algoritmi ricorsivi, dove la possibilità che i dati vengano condivisi tra le attività più recenti anziché tra quelle meno recenti è maggiore. La possibilità di eseguire i nuovi elementi per primi comporta un numero minore di tentativi di accesso alla cache non riusciti e di errori di pagina.

Dalla prospettiva del sistema operativo, l'acquisizione del lavoro non è equa. Tuttavia, quando un'applicazione implementa un algoritmo o un'attività per l'esecuzione in parallelo, l'equità tra le sottoattività non è sempre importante. L'aspetto realmente rilevante è la rapidità con cui viene completata l'attività complessiva. Per altri algoritmi, FIFO rappresenta la strategia di pianificazione appropriata.

Comportamento in vari sistemi operativi

In Windows XP e Windows Vista, le applicazioni che utilizzano il runtime di concorrenza si comportano in modo simile, ad eccezione del fatto che in Windows Vista sono state migliorate le prestazioni dell'heap.

In Windows 7 e Windows Server 2008 R2, il sistema operativo supporta inoltre la concorrenza e la scalabilità. Questi sistemi operativi supportano, ad esempio, computer con oltre 64 thread di hardware. Un'applicazione esistente che utilizza l'API Windows deve essere modificata in modo da sfruttare i vantaggi di queste nuove funzionalità. Tuttavia, un'applicazione che utilizza il runtime di concorrenza implementa automaticamente queste funzionalità e non richiede alcuna modifica.

In Windows 7 e Windows Server 2008 R2 viene aggiunto il supporto dei thread pianificabili in modalità utente. I thread pianificabili in modalità utente consentono alle utilità di pianificazione in modalità utente e al kernel di pianificare il lavoro in modo più efficiente. Sebbene la pianificazione in modalità utente mantenga la precedenza, l'efficienza viene incrementata consentendo alle applicazioni e alle librerie di eseguire la pianificazione cooperativa senza le transizioni del kernel. La pianificazione in modalità utente restituisce inoltre il controllo all'applicazione quando un thread viene bloccato nel kernel, in modo che l'applicazione possa eseguire ulteriori attività durante la porzione di tempo restante. Il runtime di concorrenza utilizza automaticamente la pianificazione in modalità utente quando è supportata dal sistema operativo. Per ulteriori informazioni sulla pianificazione in modalità utente, vederePianificazione in modalità utente.

[vai all'inizio]

Confronto tra il runtime di concorrenza e OpenMP

Il runtime di concorrenza consente diversi modelli di programmazione. Questi modelli possono sovrapporsi ai modelli di altre librerie o integrarsi con essi. In questa sezione vengono confrontati il runtime di concorrenza e OpenMP.

Il modello di programmazione OpenMP è definito da uno standard aperto e dispone di associazioni ben definite ai linguaggi di programmazione Fortran e C/C++. Le versioni 2.0 e 2.5 di OpenMP sono particolarmente adatte per gli algoritmi paralleli che sono iterativi, ovvero eseguono l'iterazione parallela su una matrice di dati. OpenMP è molto efficiente quando il grado di parallelismo è predeterminato e corrisponde alle risorse disponibili nel sistema. Il modello OpenMP rappresenta un sistema valido soprattutto per il calcolo a elevate prestazioni, che prevede la distribuzione di problemi di calcolo molto estesi tra le risorse di elaborazione di un unico computer. In questo scenario, l'ambiente dell'hardware è noto e lo sviluppatore potrà accedere in modo esclusivo alle risorse di elaborazione quando viene eseguito l'algoritmo.

Tuttavia, altri ambienti di elaborazione meno vincolati possono non rappresentare una corrispondenza valida per OpenMP. I problemi ricorsivi, quale l'algoritmo QuickSort o la ricerca in una struttura ad albero di dati, sono ad esempio più difficili da implementare tramite OpenMP. Il runtime di concorrenza completa le funzionalità di OpenMP offrendo la libreria PPL (Parallel Patterns Library) e la libreria di agenti asincroni. A differenza di OpenMP, il runtime di concorrenza fornisce un'utilità di pianificazione dinamica che si adatta alle risorse disponibili e regola il grado di parallelismo in base alla modifica dei carichi di lavoro.

Molte delle funzionalità del runtime di concorrenza possono essere estese. È inoltre possibile combinare le funzionalità esistenti per crearne delle nuove. Poiché OpenMP si basa sulle direttive del compilatore, non può essere esteso facilmente.

Per ulteriori informazioni sul confronto tra il runtime di concorrenza e OpenMP e su come eseguire la migrazione del codice OpenMP esistente per l'utilizzo del runtime di concorrenza, vedere Migrazione da OpenMP al runtime di concorrenza.

[vai all'inizio]

Vedere anche

Riferimenti

Cenni preliminari sull'API Windows

Concetti

Runtime di concorrenza

Cenni preliminari sul runtime di concorrenza

PPL (Parallel Patterns Library)

Libreria di agenti asincroni

Altre risorse

OpenMP in Visual C++

Cronologia delle modifiche

Data

Cronologia

Motivo

Luglio 2010

Sono state aggiunte informazioni sulla migrazione e sull'interoperabilità.

Miglioramento delle informazioni.