bezpieczeństwo wątków MPI send przy użyciu wątków utworzonych za pomocą std:: async
Zgodnie z ta strona , korzystanie z {[1] } jest bezpieczne. Jednak w mojej aplikacji często (nie zawsze) napotykam impasy lub dostaję błędy segmentacji. Zamknięcie każdego wywołania metod {[2] } za pomocą mutex.lock()
i mutex.unlock()
konsekwentnie usuwa blokady martwe, jak również segfaults.
Tak tworzę wątki:
const auto communicator = std::make_shared<Communicator>();
std::vector<std::future<size_t>> handles;
for ( size_t i = 0; i < n; ++i )
{
handles.push_back(std::async(std::launch::async, foo, communicator));
}
for ( size_t i = 0; i < n; ++i )
{
handles[i].get();
}
Communicator
jest klasą, która posiada std::mutex
member i wywołuje wyłącznie metody takie jak MPI::COMM_WORLD.Send()
i MPI::COMM_WORLD.Recv()
. Nie stosuję żadnych innych metod wysyłanie/odbieranie za pomocą MPI. foo
bierze const std::shared_ptr<Commmunicator> &
jako argument.
Moje pytanie: czy obiecane przez MPI bezpieczeństwo wątków nie jest kompatybilne z wątkami utworzonymi przez std::async
?
2 answers
Wątek-bezpieczeństwo 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 wykonujących połączenia MPI naraz. 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ła na odpowiednim poziomie obsługi wątku. Obecnie standard MPI definiuje cztery poziomy obsługi wątków:
-
MPI_THREAD_SINGLE
- oznacza, że użytkownik kod jest jednowątkowy. Jest to domyślny poziom, na którym inicjowane jest MPI, jeśli używane jestMPI_Init()
; -
MPI_THREAD_FUNNELED
- oznacza, że kod użytkownika jest wielowątkowy, ale tylko główny wątek wywołuje 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 i wszystkie wątki mogą wykonywać połączenia MPI w dowolnym momencie bez / align = "left" /
Aby zainicjować MPI z obsługą wątku, należy 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 kod z przestarzały (i usunięty z MPI-3) wiązań C++:
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 wątków są uporządkowane w następujący sposób: MPI_THREAD_SINGLE
MPI_THREAD_FUNNELED MPI_THREAD_SERIALIZED 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 if (...)
jest tak napisany.
MPI_Init(&argc, &argv)
na odpowiednik MPI_Init_thread(&argc, &argv, MPI_THREAD_SINGLE, &provided)
. Implementacje nie muszą inicjalizować dokładnie na żądanym poziomie - zamiast tego mogą inicjalizować na dowolnym innym poziomie (wyższym lub niższym), który jest zwracany w argumencie wyjściowym provided
.
Aby uzyskać więcej informacji-patrz §12.4 standardu MPI, dostępny bezpłatnie tutaj .
W większości implementacji MPI, obsługa wątków na poziomie MPI_THREAD_SINGLE
jest w rzeczywistości równoważna tej dostarczonej na poziomie MPI_THREAD_SERIALIZED
- dokładnie to, co obserwujesz w swoim case.
Ponieważ nie określiłeś, której implementacji MPI używasz, oto przydatna lista.
Powiedziałem już, że Open MPI musi być skompilowane z włączonymi odpowiednimi flagami, aby móc obsługiwać MPI_THREAD_MULTIPLE
. Ale jest jeszcze jeden haczyk - komponent InfiniBand nie jest bezpieczny dla wątków i dlatego Open MPI nie używałoby natywnej komunikacji InfiniBand, gdy inicjowane są na pełnym poziomie obsługi wątków.
MPI Intela występuje w dwóch różnych smakach - jednym z i jednym bez obsługa pełnej wielowątkowości. Obsługa wielowątkowa jest włączona przez przekazanie opcji -mt_mpi
do pakietu kompilatora MPI, który umożliwia łączenie się z wersją MT. Opcja ta jest również domyślna, jeśli włączona jest obsługa OpenMP lub autoparalleliser. Nie wiem, jak działa sterownik InfiniBand w IMPI, gdy włączona jest obsługa pełnego wątku.
MPICH(2) nie obsługuje InfiniBand, dlatego jest bezpieczny dla wątków i prawdopodobnie najnowsze wersje zapewniają MPI_THREAD_MULTIPLE
wsparcie z box.
MVAPICH jest podstawą, na której zbudowany jest Intel MPI i obsługuje InfiniBand. Nie mam pojęcia, jak zachowuje się na pełnym poziomie wsparcia wątku, gdy jest używany na maszynie z InfiniBand.
Uwaga na temat wielowątkowej obsługi InfiniBand jest ważna, ponieważ wiele klastrów obliczeniowych używa obecnie tkanin InfiniBand. Po wyłączeniu komponentu IB (openib
BTL w Open MPI) większość implementacji MPI przechodzi na inny protokół, na przykład TCP / IP (tcp
BTL w Open MPI), który powoduje znacznie wolniejszą i bardziej utajoną komunikację.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-12 16:51:00
Istnieją cztery poziomy bezpieczeństwa wątków MPI, nie wszystkie z nich są obsługiwane przez każdą implementację: MPI_THREAD_SINGLE, MPI_THREAD_FUNNELED, MPI_THREAD_SERIALIZED i mpi_thread_multiple. Ostatni, który pozwala procesowi mieć wiele wątków, które mogą jednocześnie wywoływać funkcje MPI, jest prawdopodobnie tym, który Cię interesuje. Przede wszystkim musisz się upewnić, że Twoja implementacja obsługuje MPI_THREAD_SERIALIZED.
Wymagany poziom bezpieczeństwa gwintu musi być określony przez wywołanie MPI_Init_thread
. Po wywołaniu MPI_Init_thread
powinieneś być w stanie bezpiecznie wywoływać funkcje MPI w wątkach boost (POSIX) utworzonych samodzielnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-12 16:51:57