Parallelizzazione: scelta del modello di comunicazione

4

Dichiarazione di non responsabilità: se non sei interessato alla parallelizzazione (sui cluster), questa domanda probabilmente non ti interessa e probabilmente non vale la pena leggerla.

TL; DR: cerco un modello di comunicazione (preferibilmente compatibile con MPI ) che assicuri in modo efficiente che ogni riga di dati venga elaborata una volta. Leggi anche il prossimo paragrafo per sapere cosa intendo per linea di dati.

Si consideri il seguente problema: Un algoritmo prende una linea di dati (nel mio caso, una matrice di numeri interi con dimensione fissa) e produce varie linee di dati che poi devono essere elaborate dallo stesso algoritmo. Ogni riga dati univoca deve essere elaborata solo una volta, poiché l'esito è puramente deterministico. L'insieme di linee dati univoche è finito, quindi dopo un numero finito di chiamate ricorsive di questo algoritmo produce l'intero set. L'obiettivo è trovare questo set.

Ho già implementato l'algoritmo e ho anche implementato una parallelizzazione. Ovviamente, dal momento che è necessario elaborare ogni riga di dati univoca , in ogni momento tutte le linee di dati attualmente non elaborate possono essere elaborate da processori diversi in parallelo.

D'altra parte, la parallelizzazione introduce il problema di impedire ai diversi processori di eseguire lavori ridondanti.

Un'implementazione banale dovrebbe inviare linee di dati ai processori, raccogliere tutti i risultati e distribuire nuovamente. Questo può essere inefficiente dal momento che gli elenchi dei risultati (possibilmente di grandi dimensioni) devono essere uniti prima che qualsiasi ulteriore lavoro possa essere svolto. Se tutti gli elenchi vengono restituiti nello stesso periodo, il master viene sopraffatto dalla mera quantità di dati mentre tutti gli slave rimangono inattivi fino al completamento di tutte le operazioni di fusione.

Il mio modello di comunicazione (per quanto mi sembra, migliorato) è ancora fondamentalmente Master-Slave:

Questo è ciò che fa il Maestro:

Distribute initial chunk of data lines to slaves
While there is at least one active slave
  for each active slave
    Request data line
    if slave doesn't have a data line
      set slave inactive, break
    else
      if the data line was previously processed
        break
      endif
      if there is an inactive slave
        send the data line to inactive slave and mark that slave as active
        send the sending slave a notification to not process the data line
      else
        notify the slave to process the data line it just sent
      endif
    endif
  endfor
endwhile

Ogni slave fa questo:

while true
 wait for request
 if data line available
   send it
   wait for master to say if the line should be processed here
   process if necessary
   go back to beginning
 else
   notify master
   wait for master to send a data line
   process the received line
   go back to beginning
 endif

Lo slave gestisce il proprio elenco locale di righe di dati elaborate e non elaborate. Per ogni richiesta, un elemento di quelli non elaborati viene spostato in quelli elaborati. Solo le voci univoche tra i due elenchi sono memorizzate.

In conclusione: solo il master conosce l'intero set di linee elaborate. uno slave elabora una linea dati se e solo se il master dice che non è stato elaborato in precedenza. Il Master non conosce i risultati per ciascuna linea di dati finché non ha richiesto tutte le linee disponibili da ciascun slave.

Per quanto posso pensare, questo modello di comunicazione dell'elenco di linee dati elaborate è piuttosto efficiente, ma sono nuovo nel mondo della parallelizzazione, specialmente nel mondo della parallelizzazione su un cluster.

Quali sono altri modi per comunicare in modo efficiente le linee dati tra più processori per garantire che ogni riga di dati venga elaborata esattamente una volta?

Questa domanda non è fondamentalmente legata alla combinazione di C++ e MPI , anche se qualsiasi risposta che riflette il modo in cui funziona l'interfaccia Message Passing è molto apprezzata.

    
posta stefan 17.02.2013 - 12:25
fonte

1 risposta

1

Disclaimer: non ho alcuna esperienza MPI / clustering
Fai attenzione anche al mio possibile uso errato della terminologia.

La mia idea di base è di applicare una funzione di hash alle linee dati di input e output. Calcola un intero K (tra 1 e NumSlaves) dall'hash per decidere quale (K) dello slave (NumSlaves) dovrebbe processare questa linea di dati.

Ogni slave avrà un intervallo hash. Una riga di dati verrà elaborata dallo slave se l'hash della riga di dati cade nell'intervallo hash dello slave.

Questo schema di base richiede che gli schiavi comunichino direttamente tra loro. Il master fungerà da custode del journal, che riceve una copia degli output calcolati da ciascun nodo ma non partecipa all'assegnazione delle attività.

Quando uno slave ricava una o più linee dati di uscita da una linea dati di input, calcola questa funzione di hash su ciascuna riga di dati di uscita e decide per ciascuno uno slave che la elabora.

Questo schema di base non fornisce tolleranza agli errori o modifica del numero di slave in fase di esecuzione; a meno che non vengano utilizzate altre tecniche di elaborazione distribuita (ad esempio hashing coerente, ecc.)

Ogni slave deve memorizzare nella cache tutte le righe di dati che rientrano nel suo intervallo hash, per evitare il ricalcolo.

Questo schema potrebbe richiedere più comunicazioni rispetto al tuo schema attuale, ma potrebbe essere migliore nel prevenire il lavoro duplicato.

    
risposta data 17.02.2013 - 23:41
fonte

Leggi altre domande sui tag