Redukcja wprowadzona przy użyciu MPI_Allreduce()
jest odtwarzalna, o ile używasz tej samej liczby procesorów, pod warunkiem, że implementacja przestrzega następującej uwagi w sekcji 5.9.1 standardu MPI-2.2.
Porady dla realizatorów . Zdecydowanie zaleca MPI_REDUCE
się implementację, aby uzyskać ten sam wynik za każdym razem, gdy funkcja jest stosowana do tych samych argumentów, pojawiających się w tej samej kolejności. Należy pamiętać, że może to uniemożliwić optymalizacje wykorzystujące fizyczną lokalizację procesorów. ( Koniec porady dla wdrażających .)
Jeśli chcesz zagwarantować odtwarzalność za wszelką cenę, możesz postępować zgodnie z wytycznymi w następnym akapicie:
Porady dla użytkowników . Niektóre aplikacje mogą nie być w stanie zignorować niesocjacyjnego charakteru operacji zmiennoprzecinkowych lub mogą wykorzystywać operacje zdefiniowane przez użytkownika (patrz rozdział 5.9.5), które wymagają specjalnego polecenia redukcji i nie mogą być traktowane jako asocjacyjne. Takie aplikacje powinny wyraźnie egzekwować kolejność oceny. Na przykład w przypadku operacji wymagających ścisłej kolejności oceny od lewej do prawej (lub od prawej do lewej) można to zrobić poprzez zebranie wszystkich operandów w jednym procesie (np. Za pomocą
MPI_GATHER
), stosując operację redukcji w pożądanej kolejności (np. z
MPI_REDUCE_LOCAL
) i, jeśli to konieczne, transmituj lub rozpraszaj wynik do innych procesów (np. z MPI_BCAST
). ( Koniec porady dla użytkowników ).
W szerszym schemacie rzeczy wydajne algorytmy dla większości aplikacji wykorzystują lokalizację. Ponieważ algorytm jest naprawdę inny, gdy działa na innej liczbie procesów, po prostu nie jest praktyczne dokładne odtwarzanie wyników, gdy jest uruchamiany na innej liczbie procesów. Możliwym wyjątkiem jest układ wielosieciowy z tłumionym wygładzaczem Jacobiego lub wielomianowy (np. Czebiszew), w którym możliwe jest bardzo dobre działanie tej prostej metody.
Przy tej samej liczbie procesów często korzystne jest przetwarzanie wiadomości w kolejności ich odbierania (np. Za pomocą MPI_Waitany()
), co wprowadza niedeterminizm. W takich przypadkach można zaimplementować dwa warianty: szybki, który odbiera w dowolnej kolejności, i „debugujący”, który odbiera w kolejności statycznej. Wymaga to napisania wszystkich bazowych bibliotek, aby oferowały takie zachowanie.
W celu debugowania w niektórych przypadkach można wyodrębnić część obliczeń, która nie zapewnia tego powtarzalnego zachowania, i wykonać ją nadmiarowo. W zależności od sposobu zaprojektowania komponentów zmiana ta może być niewielką ilością kodu lub być bardzo uciążliwa.