Bezpieczeństwo gwintów w MPI nie działa po wyjęciu z pudełka. Po pierwsze, musisz upewnić się, że twoja implementacja faktycznie obsługuje wiele wątków nawiązujących połączenia MPI na raz. W przypadku niektórych implementacji MPI, na przykład Open MPI, wymaga to skonfigurowania biblioteki ze specjalnymi opcjami w czasie kompilacji. Następnie musisz powiedzieć MPI, aby zainicjował na odpowiednim poziomie obsługi wątków. Obecnie standard MPI definiuje cztery poziomy obsługi wątków:
MPI_THREAD_SINGLE
- oznacza, że kod użytkownika jest jednotomowy. Jest to domyślny poziom, przy którym inicjowany jest MPI, jeśli użyto MPI_Init()
;
MPI_THREAD_FUNNELED
- oznacza, że kod użytkownika jest wielowątkowy, ale tylko główny wątek wywołuje połączenia MPI. Głównym wątkiem jest ten, który inicjalizuje bibliotekę MPI;
MPI_THREAD_SERIALIZED
- oznacza, że kod użytkownika jest wielowątkowy, ale wywołania do biblioteki MPI są serializowane;
MPI_THREAD_MULTIPLE
- oznacza, że kod użytkownika jest wielowątkowy, a wszystkie wątki mogą wykonywać połączenia MPI w dowolnym czasie bez żadnej synchronizacji.
W celu zainicjowania MPI przy pomocy gwintu, trzeba użyć MPI_Init_thread()
zamiast MPI_Init()
:
int provided;
MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
if (provided < MPI_THREAD_MULTIPLE)
{
printf("ERROR: The MPI library does not have full thread support\n");
MPI_Abort(MPI_COMM_WORLD, 1);
}
równoważny kodu z zastąpiony (i usuwane z MPI-3) C++ wiązania:
int provided = MPI::Init_thread(argc, argv, MPI::THREAD_MULTIPLE);
if (provided < MPI::THREAD_MULTIPLE)
{
printf("ERROR: The MPI library does not have full thread support\n");
MPI::COMM_WORLD.Abort(1);
}
poziomy wsparcia Temat są sortowane tak: MPI_THREAD_SINGLE
< MPI_THREAD_FUNNELED
< MPI_THREAD_MULTIPLE
, więc każdy inny podany poziom, inny niż MPI_THREAD_MULTIPLE
, miałby niższą wartość liczbową - dlatego powyższy kod zapisano w ten sposób. if (...)
MPI_Init(&argc, &argv)
jest odpowiednikiem MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided)
. Implementacje nie są wymagane do zainicjowania dokładnie na żądanym poziomie - zamiast tego mogą być inicjowane na dowolnym innym poziomie (wyższym lub niższym), który jest zwracany w argumencie wyjściowym provided
.
Więcej informacji - patrz §12.4 standardu MPI, swobodnie dostępny here.
W większości implementacji MPI, wsparcie na poziomie MPI_THREAD_SINGLE
wątek jest rzeczywiście równoważne pod warunkiem, że na poziomie MPI_THREAD_SERIALIZED
- dokładnie to, co można zaobserwować w Twoim przypadku.
Ponieważ nie określiłeś, która wersja MPI jest używana, oto przydatna lista.
już mówiłem, że Otwarte MPI musi być skompilowany z odpowiednimi flagami włączony żeby wesprzeć MPI_THREAD_MULTIPLE
. Ale jest jeszcze jeden haczyk - komponent InfiniBand nie jest bezpieczny dla wątków, a zatem Open MPI nie będzie używał natywnej komunikacji InfiniBand, gdy zostanie zainicjowany na poziomie pełnej obsługi wątków.
Intel MPI występuje w dwóch różnych smakach - jednym z i jednym bez wsparcia dla pełnej wielowątkowości. Obsługę wielowątkową można włączyć, przekazując opcję -mt_mpi
do wrappera MPI kompilatora, który umożliwia łączenie z wersją MT. Ta opcja jest również domniemana, jeśli obsługa OpenMP lub autoparalleliser jest włączona. Nie wiem, jak działa sterownik InfiniBand w IMPI, gdy włączona jest pełna obsługa wątków.
MPICH (2) nie obsługuje InfiniBand, w związku z tym jest bezpieczny dla wątków i prawdopodobnie najnowsze wersje zapewniają MPI_THREAD_MULTIPLE
obsługę zaraz po wyjęciu z pudełka.
MVAPICH jest podstawą do budowy Intel MPI i obsługuje InfiniBand. Nie mam pojęcia, jak zachowuje się na pełnym poziomie obsługi wątków, gdy jest używany na komputerze z InfiniBand.
Nota o wielowątkowym wsparcia InfiniBand to ważne, ponieważ wiele klastrów obliczeniowych obecnie używać tkanin InfiniBand. Gdy składnik IB (openib
BTL w Open MPI) jest wyłączony, większość implementacji MPI przechodzi na inny protokół, na przykład TCP/IP (tcp
BTL w Open MPI), co powoduje znacznie wolniejszą i bardziej utajoną komunikację.
Bardzo pomocna odpowiedź, dziękuję bardzo! Ponieważ muszę pracować z wieloma różnymi implementacjami mpi, niestety mam opcję użycia mojego własnego muteksa, ale to wciąż przyzwoite rozwiązanie. – stefan
Zawsze masz opcję _try_ do zainicjowania MPI z pełną obsługą wątków i użycia mutex tylko, jeśli nie otrzymasz żądanego poziomu obsługi wątków. Zauważ, że możliwość wykonywania serializowanych wielowątkowych wywołań MPI w 'MPI_THREAD_SINGLE' lub' MPI_THREAD_FUNNELED' jest ** nie ** w sposób określony przez standard. –
tak, to jest rzeczywiście możliwość. Jednak z punktu widzenia projektowania nie zrobiłbym tego. Obejmuje to warunkowe w całym kodzie komunikacji lub warunkowe tworzenie obiektu komunikatora. Nie podoba mi się to, więc postanowiłem w pełni polegać na własnym muteksie. To tylko trochę czystsze imho. – stefan