Quando dovrei usare il parallelismo? [chiuso]

5

Dopo aver chiesto questo domanda, ho capito che il parallelismo potrebbe non essere sempre buono.

Finora posso vedere che il parallelismo (sotto c #) è

  • Un po 'complicato in termini di codice
  • Probabilmente inserirà alcune complicazioni di concorrenza
  • Non sarà sempre più veloce

Sto osservando il parallelismo perché voglio rendere le applicazioni esistenti e nuove più veloci, ma ora vedo che non è un proiettile argentato.

Quando dovrei usarlo? ci sono buone pratiche? È solo una perdita di tempo nella maggior parte dei casi? È adatto per un tipo specifico di applicazioni?

Non vedo l'ora di approfondire l'argomento.

    
posta Mithir 03.05.2012 - 09:23
fonte

8 risposte

6

Anche se non è sicuramente un proiettile d'argento, la Libreria parallela attività di .Net 4 può semplificare alcuni aspetti della parallelizzazione del codice, una volta che hai già preso la decisione di farlo.

Per rispondere alla tua domanda, ci sono certamente differenze tra i tipi di problemi, in termini di quanto beneficio ottengono dall'essere parallelizzati. Alcuni problemi sono indicati come imbarazzantemente parallelo , e la definizione ha molto a che fare con la quantità di comunicazione necessaria tra le attività .

Anche se sono sicuro che potresti trovare una serie di linee guida per i tipi di attività che traggono grande beneficio dalla parallelizzazione in generale (es. vedi la risposta di linkerro per alcuni), puoi anche semplicemente analizzare il problema e fare una chiamata da solo (supponendo che tu capisca i concetti a un livello abbastanza basso).

Detto questo, c'è molto da dire per semplicità e leggibilità del codice. In generale, a meno che tu non abbia a che fare con problemi che traggono grande beneficio dal parallelismo e / o dalle prestazioni è una priorità, tentare di rendere tutto parallelo è solo complicare le cose e morderti. La maggior parte delle volte, ci sono posti migliori dove spendere la tua intelligenza in più:)

    
risposta data 03.05.2012 - 10:00
fonte
4

Ci sono alcuni casi in cui dovresti usare il parallelismo, il caso più semplice è di eseguire un grosso compito in background per rimanere reattivo alla GUI. È un parallelismo di compiti. Un altro caso è quando devi elaborare molti dati: decodifica video, risoluzione dei problemi di ottimizzazione e così via. Questo tipo di parallelismo è chiamato parallelismo dei dati. Nel caso di parallelismo dei dati un'attività viene elaborata più velocemente, poiché tutti i blocchi di dati vengono elaborati in modo indipendente. Ma per il parallelismo delle attività le prestazioni non sono sempre lo scopo principale. Spesso dovresti usarlo per migliorare l'usabilità.

    
risposta data 03.05.2012 - 10:50
fonte
3

Supponendo che stiamo parlando di applicazioni di piattaforma, penso che il prossimo-sempre-end-up necessiti di una qualche forma di parallelismo in quanto la tua applicazione diventa più complessa (come per il materiale di lettura raccomandato da Gnat). C'è sempre un grande file da caricare, o un reclamo da parte del cliente che alcune dipendenze del servizio web sono troppo lente.

Tuttavia, fai attenzione a utilizzare i thread di vaniglia e le primitive di sincronizzazione di base, perché il multithreading è difficile ; invece, prova a utilizzare primitive, pattern e componenti di livello superiore (troverai molte cose fantastiche per iniziare nei namespace System.Threading.Tasks e System.Collections.Concurrent). Ancora più importante, con l'aumentare della complessità della soluzione, evita trucchi intelligenti .

In particolare, la tua amichevole applicazione di piattaforma di quartiere in C # è probabile che disponga di una pompa di messaggi dell'interfaccia utente e di roba in esecuzione in background, al fine di impedire il blocco dell'interfaccia utente o b) di sfruttare più CPU logiche. Una buona lista di decisioni su "come parallelizzare le cose pesanti sullo sfondo" sarebbe:

  • se l'attività non è semplicemente intensiva della CPU, ma può impiegare molto tempo ad attendere (ad esempio per IO o per altre attività), inviarla al Pool di thread. Un buon schema qui è quello di inviare al TP solo la chiamata che potrebbe farti aspettare - il framework ha già qualcosa per questo, troverai i metodi Begin * / End * in cui potresti aspettare a lungo - e riportare indietro ad alcuni contesto sicuro (ad esempio il thread dell'interfaccia utente) quando il pollo è finito. In questo modo, la tua esposizione ai problemi di parallelismo è bassa, ed è destinata ad essere ridicolmente bassa nelle prossime versioni di .NET, con asincrono e attesa.

  • attività non omogenee con bassa granularità - di solito è il parallelismo delle attività, il modello di progettazione Comando / Attività è tuo amico, inoltre, prova a prendere a prestito da programmazione funzionale - evitare dati mutabili e condivisi, utilizzare le continuazioni - e utilizzare il framework (in particolare: TPL , o almeno un BlockingCollection che implementa un produttore-consumatore);

  • attività omogenee con alta granularità - di solito è il parallelismo dei dati, in cui le strutture dati e gli algoritmi che distribuisci fanno la differenza. Cerca di isolare le unità di lavoro con questo profilo dal resto della tua logica e considera di procedere puramente funzionale con esso - usa map-reduce come buon suggerimento.

risposta data 03.05.2012 - 17:01
fonte
2

Tutte le attività non sono state create uguali. Alcuni compiti si prestano al parallelismo in modo naturale. Ad esempio, considera che stai creando un sito web di viaggi come Kayak. Una delle cose più importanti da fare è utilizzare le API fornite da provider di ricerca come British Airways, Singapore Airways ecc., È possibile impostare un thread diverso su API diverse in modo che, il recupero possa essere eseguito in parallelo. Se un thread non restituire il risultato in tempo, abortire (potrebbe essere). Come puoi immaginare, è molto difficile eseguire questa attività senza usare la concorrenza.

Con i processori che arrivano con più core in questi giorni, la programmazione simultanea sta diventando sempre più rilevante.

    
risposta data 03.05.2012 - 10:21
fonte
1

Lo uso su applicazioni lato server dove ho 8 core a portata di mano. Si tratta di un miglioramento della velocità della tua applicazione che funziona con i big data set.

Tuttavia, lo uso solo quando so che ci sono operazioni che possono essere parallelizzate: colpi al database (usando diverse connessioni dal pool di connessioni), richieste ai servizi web, disco IO (questo è discutibile ma continuo la presunzione che i thread inizieranno a funzionare non appena vengono ordinati i loro IO e non devono aspettare che gli altri facciano il loro lavoro).

Tutto ciò porta a miglioramenti marginali, ma su serie di dati di grandi dimensioni, il parallelo vince sul seriale in queste condizioni.

Ancora, io solo quando l'interazione dell'utente è influenzata da operazioni lente, poiché scrivere il codice per eseguire operazioni parallele potrebbe non essere banale anche con plinq.

    
risposta data 03.05.2012 - 09:40
fonte
1

Il parallelismo è uno strumento molto importante da avere nella tua cintura, ma per impararlo bene devi usarlo molto finché non ne prendi il controllo. Sei fortunato ad usare C # perché TPL è la più grande libreria che abbia mai visto e combinato con LINQ e estensioni di metodo è semplicemente killer.

Rispondere specificamente alle tue domande.

Quando dovrei usarlo?

Ci sono fondamentalmente due motivi per cui potresti voler usare TPL:

  1. Elaborazione in background: vuoi assicurarti che la tua applicazione sia ancora reattiva mentre esegui un'operazione che potrebbe richiedere del tempo. Devi studiare e capire come effettuare chiamate in modo asincrono.
  2. Elaborazione parallela: vuoi assicurarti che diversi thread vengano utilizzati per eseguire le attività in parallelo, facendo in modo che il tuo codice funzioni più velocemente (che funziona meglio su sistemi multi-core).

TPL ti aiuterà molto in entrambi gli scenari (C # 5.0 ha alcuni nuovi trucchi speciali che trasformano la programmazione asincrona in cose da bambini).

Ci sono delle buone pratiche?

Sì, ci sono. Ad esempio, per Windows Form è possibile utilizzare BackgroundWorker perché consente di gestire il fatto che non è possibile effettuare alcuna chiamata agli oggetti dell'interfaccia utente al di fuori dei propri thread.

Ce ne sono molti altri, ma varieranno a seconda di cosa stai facendo esattamente (ASP.NET, WPF, Silverlight, WinForms e così via). La maggior parte delle volte utilizzo MSDN e StackOverflow ma il fatto è che più usi la TPL in generale, più acquisirai conoscenza e più facile sarà usarla e sapere quando il parallelismo è una soluzione adeguata o quando non lo è.

Nella maggior parte dei casi è solo una perdita di tempo? È adatto per un tipo specifico di applicazioni?

Non esiste una risposta universale a questa domanda, ogni progetto deve essere messo in prospettiva e analizzato. Esistono certamente tipi specifici di applicazioni più adatti al parallelismo. Nell'elaborazione parallela, ad esempio:

  • Giochi
  • numero di applicazioni di crunch
  • elaborazione di immagini e video
  • elaborazione dati

In elaborazione in background qualsiasi tipo di applicazione con un'interfaccia utente e gestisce attività che richiedono più di un paio di secondi. Qui puoi trovare articoli eccellenti su C # 5.0 async:

link

Le applicazioni mobili stanno riportando l'attenzione su questo argomento perché le piattaforme mobili semplicemente non hanno lo stesso livello di potenza di elaborazione dei desktop e solitamente gli utenti hanno una pazienza molto breve durante l'esecuzione di un'app. Vedi questo articolo per esempio su come l'elaborazione in background può creare l'impressione che la tua applicazione sia velocissima:

link

Se vuoi imparare, non c'è niente di meglio che provarlo più e più volte finché non vedi i risultati per te stesso (buoni o cattivi).

    
risposta data 04.05.2012 - 05:06
fonte
0

La programmazione e il parallelismo simultanei all'interno di un processo tramite multi-threading sono molto potenti ma anche complicati da ottenere a causa di tutti i problemi con i dati condivisi: deadlock, aggiornamenti persi, ecc.

Tuttavia, ci sono situazioni in cui può essere molto utile (o persino necessario):

  1. Per efficienza: se hai più core puoi eseguire thread diversi su core diversi.
  2. Per modularità: hai diviso la tua implementazione in compiti diversi e li hai eseguiti separatamente.
  3. Perché è un requisito della tua domanda, ad es. vuoi recuperare i dati da un server mentre l'applicazione continua a interagire con l'utente.

Riguardo a 2, trovo questo approccio molto efficace per l'implementazione di flussi di lavoro in cui ci sono diversi processori (virtuali) che trasformano flussi di dati. I processori comunicano attraverso alcuni tipi di tubi, ad es. il flusso di dati di uscita del processore A è il flusso di input del processore B.

In questo caso tutto l'impegno nella gestione della concorrenza può essere localizzato nell'implementazione della classe del flusso di dati (una sorta di coda thread-safe con metodi, ad esempio push_front (), pop_back ()): è possibile incapsulare tutto il gestione della concorrenza dei dati nell'implementazione di questa classe di code e quindi programmare ciascun nodo del flusso di lavoro come se fosse l'unico thread in esecuzione sul sistema.

Seguendo un'idea simile ma più generale, potrebbe essere interessante dare un'occhiata al modello dell'attore. In questo modello vedi ogni thread come un oggetto che invia e riceve messaggi in modo da non dover gestire direttamente i thread. Le lingue che includono un supporto per attori standard sono Erlang e Scala . Altrimenti è necessaria una libreria appropriata per questo, ad es. akka (Scala, Java), Theron (C ++). Per le implementazioni del modello attore in C #, guarda le risposte a questa domanda .

Bottom-line, i thread possono essere molto utili ma, se intendi usarli in modo non banale, ti consiglierei di usare un approccio più astratto usando alcune librerie.

    
risposta data 04.05.2012 - 08:02
fonte
-1

I percorsi di codice che non svolgono un lavoro sostanziale non sarebbero molto utili da eseguire in parallelo. Consulta la legge di Amdahl per i dettagli.

    
risposta data 03.05.2012 - 10:49
fonte

Leggi altre domande sui tag