Czy async (uruchomienie :: async) w C ++ 11 sprawia, że pule wątków stają się przestarzałe w celu uniknięcia kosztownego tworzenia wątków?
Jest to luźno związane z tym pytaniem:Czy std :: thread jest połączony w C ++ 11?. Chociaż pytanie różni się, intencja jest taka sama:
Pytanie 1: Czy nadal ma sens używanie własnych pul wątków (lub bibliotek innych firm), aby uniknąć kosztownego tworzenia wątków?
Wniosek z drugiego pytania był taki, że nie można na nim polegaćstd::thread
do łączenia (może lub nie). Jednak,std::async(launch::async)
wydaje się mieć o wiele większą szansę na połączenie.
Nie sądzę, żeby był wymuszony przez standard, ale IMHO oczekiwałbym, że wszystkie dobre implementacje C ++ 11 będą używać puli wątków, jeśli tworzenie wątków jest wolne. Tylko na platformach, na których tworzenie nowego wątku jest niedrogie, spodziewałbym się, że zawsze pojawią się nowe wątki.
Pytanie 2: Tak myślę, ale nie mam faktów, które by to udowodniły. Mogę się bardzo pomylić. Czy to wykształcone przypuszczenie?
Na koniec podałem przykładowy kod, który najpierw pokazuje, jak myślę, że tworzenie wątków może być wyrażone przezasync(launch::async)
:
Przykład 1:
thread t([]{ f(); });
// ...
t.join();
staje się
auto future = async(launch::async, []{ f(); });
// ...
future.wait();
Przykład 2: Ogień i zapomnij wątek
thread([]{ f(); }).detach();
staje się
// a bit clumsy...
auto dummy = async(launch::async, []{ f(); });
// ... but I hope soon it can be simplified to
async(launch::async, []{ f(); });
Pytanie 3: Czy woliszasync
wersje dothread
wersje?
Reszta nie jest już częścią pytania, ale tylko dla wyjaśnienia:
Dlaczego wartość zwracana musi być przypisana do zmiennej fikcyjnej?
Niestety, obecny standard C ++ 11 wymusza przechwycenie zwracanej wartościstd::async
w przeciwnym razie wykonywany jest destruktor, który blokuje się aż do zakończenia akcji. Jest przez niektórych uważany za błąd w standardzie (np. Przez Herb Suttera).
Ten przykład zcppreference.com dobrze to ilustruje:
{
std::async(std::launch::async, []{ f(); });
std::async(std::launch::async, []{ g(); }); // does not run until f() completes
}
Kolejne wyjaśnienie:
wiem topule wątków mogą mieć inne uzasadnione zastosowania, ale w tym pytaniu interesuje mnie tylko unikanie kosztownych kosztów tworzenia wątków.
Sądzę, że nadal istnieją sytuacje, w których pule wątków są bardzo przydatne, zwłaszcza jeśli potrzebujesz większej kontroli nad zasobami. Na przykład serwer może zdecydować się obsługiwać tylko określoną liczbę żądań jednocześnie, aby zagwarantować szybki czas odpowiedzi i zwiększyć przewidywalność użycia pamięci. Pule wątków powinny być tutaj w porządku.
Zmienne lokalne wątków mogą być również argumentem dla własnych pul wątków, ale nie jestem pewien, czy jest to istotne w praktyce:
Tworzenie nowego wątku za pomocąstd::thread
rozpoczyna się bez zainicjowanych zmiennych lokalnych wątków. Może tego nie chcesz.W wątkach zrodzonych przezasync
, jest dla mnie niejasne, ponieważ wątek mógł zostać ponownie użyty. Z mojego zrozumienia nie można zagwarantować, że zmienne lokalne wątków zostaną zresetowane, ale mogę się mylić.Z drugiej strony, korzystanie z własnych puli wątków (o stałym rozmiarze) daje pełną kontrolę, jeśli naprawdę tego potrzebujesz.