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?

Author: stefan, 2013-02-12

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 jest MPI_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ę.

 26
Author: Hristo Iliev,
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.

 1
Author: piokuc,
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