Di recente ho affrontato questo problema utilizzando alcune di queste risposte come punto di partenza. La cosa più utile da tenere a mente è che le boids sono una sorta di semplice simulazione n-body: ogni boid è una particella che esercita una forza sui suoi vicini.
Ho trovato difficile leggere il documento di Linde; Suggerisco invece di guardare "Fast Parallel Algorithms for Short-range Molecular Dynamics" di SJ Plimpton , a cui Linde faceva riferimento. Il documento di Plimpton è molto più leggibile e dettagliato con cifre migliori:
In breve, i metodi di decomposizione atomica assegnano permanentemente un sottoinsieme di atomi a ciascun processore, i metodi di decomposizione forzata assegnano un sottoinsieme di calcoli di forza a coppie a ciascun proc e i metodi di decomposizione spaziale assegnano una sottoregione della scatola di simulazione a ciascun proc .
Ti consiglio di provare AD. È il più facile da capire e implementare. FD è molto simile. Ecco la simulazione n-body di nVidia con CUDA utilizzando FD, che dovrebbe darti un'idea approssimativa di come la piastrellatura e la riduzione possono aiutare a superare drasticamente le prestazioni seriali.
Le implementazioni di SD sono generalmente tecniche di ottimizzazione e richiedono un certo grado di coreografia per essere implementate. Sono quasi sempre più veloci e si adattano meglio.
Questo perché AD / FD richiede la creazione di un "elenco vicino" per ogni boid. Se ogni boid deve conoscere la posizione dei suoi vicini, la comunicazione tra loro è O ( n ²). È possibile utilizzare gli elenchi dei vicini Verlet per ridurre la dimensione dell'area verificata da ogni boid, il che consente di ricostruire l'elenco ogni pochi timestep anziché ogni passaggio, ma è comunque O ( n ²). In SD, ogni cella mantiene un elenco vicino, mentre in AD / FD ogni boid ha un elenco vicino. Quindi, invece di ogni boid che comunica tra loro, ogni cellula comunica tra loro. Quella riduzione della comunicazione è da dove viene l'aumento della velocità.
Sfortunatamente il problema delle boids sabota leggermente SD. Fare in modo che ciascun processore tenga traccia di una cella è più vantaggioso quando le boid sono distribuite in qualche modo uniforme nell'intera regione. Ma vuoi che i boids si raggruppino insieme! Se il tuo gregge si comporta correttamente, la stragrande maggioranza dei tuoi processori andrà via, scambiando liste vuote tra loro e un piccolo gruppo di celle finirà per eseguire gli stessi calcoli che AD o FD farebbero.
Per far fronte a questo, puoi sia matematicamente ottimizzare la dimensione delle celle (che è costante) per minimizzare il numero di celle vuote in un dato momento, oppure utilizzare l'algoritmo Barnes-Hut per i quad-alberi. L'algoritmo BH è incredibilmente potente. Paradossalmente, è estremamente difficile implementare su architetture parallele. Questo perché un albero BH è irregolare, quindi i fili paralleli lo attraverseranno a velocità selvaggiamente variabili, con conseguente divergenza del filo. Salmon e Dubinski hanno presentato algoritmi di bisection ricorsivi ortogonali per distribuire equamente i quadrifogli tra i processori, che devono essere ripetuti ripetutamente per la maggior parte delle architetture parallele.
Come puoi vedere, siamo chiaramente nel regno dell'ottimizzazione e della magia nera a questo punto. Ancora una volta, prova a leggere il documento di Plimpton e vedi se ha senso.