Una riduzione implementata usando MPI_Allreduce()
è riproducibile se si utilizza lo stesso numero di processori, a condizione che l'implementazione osservi la seguente nota che appare nella Sezione 5.9.1 della norma MPI-2.2.
Consigli per gli implementatori . Si consiglia vivamente di MPI_REDUCE
essere implementato in modo da ottenere lo stesso risultato ogni volta che la funzione viene applicata sugli stessi argomenti, che appaiono nello stesso ordine. Si noti che ciò può impedire ottimizzazioni che sfruttano la posizione fisica dei processori. ( Fine della consulenza agli implementatori .)
Se è necessario garantire la riproducibilità a tutti i costi, è possibile seguire le linee guida nel paragrafo successivo:
Consigli agli utenti . Alcune applicazioni potrebbero non essere in grado di ignorare la natura non associativa delle operazioni in virgola mobile o potrebbero utilizzare operazioni definite dall'utente (vedere la Sezione 5.9.5) che richiedono un ordine di riduzione speciale e non possono essere trattate come associative. Tali domande dovrebbero far rispettare esplicitamente l'ordine di valutazione. Ad esempio, nel caso di operazioni che richiedono un rigoroso ordine di valutazione da sinistra a destra (o da destra a sinistra), ciò potrebbe essere fatto raccogliendo tutti gli operandi in un unico processo (ad esempio, con
MPI_GATHER
), applicando l'operazione di riduzione nell'ordine desiderato (ad es. con
MPI_REDUCE_LOCAL
) e, se necessario, trasmettere o diffondere il risultato ad altri processi (ad es. con MPI_BCAST
). ( Fine del consiglio per gli utenti .)
Nel più ampio schema di cose, algoritmi efficienti per la maggior parte delle applicazioni sfruttano la località. Poiché l'algoritmo è davvero diverso quando eseguito su un numero diverso di processi, non è pratico riprodurre esattamente i risultati quando eseguito su un numero diverso di processi. Una possibile eccezione è il multigrid con smorzatori Jacobi smorzati o polinomiali (ad es. Chebyshev), dove è possibile che questo semplice metodo funzioni molto bene.
Con lo stesso numero di processi, è spesso vantaggioso per le prestazioni elaborare i messaggi nell'ordine in cui sono ricevuti (ad es. Utilizzando MPI_Waitany()
), che introduce il non determinismo. In tali casi, è possibile implementare due varianti, quella veloce che riceve in qualsiasi ordine e una "debug" che riceve in un ordine statico. Ciò richiede che anche tutte le librerie sottostanti siano scritte per offrire questo comportamento.
Per il debug in alcuni casi, è possibile isolare parte di un calcolo che non offre questo comportamento riproducibile ed eseguirlo in modo ridondante. A seconda di come sono stati progettati i componenti, tale modifica può essere una piccola quantità di codice o molto invadente.