2012-04-24 16 views
12

próbuję programu:Ilość async/futures w C++ 11

#include <iostream> 
#include <thread> 
#include <future> 

int foo() { 
    return 0; 
} 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 10000; ++i) { 
    auto f = std::async(foo); 
    f.get(); 
    } 
    return 0; 
} 

Compiler VS11 x64.

Budowa:

cl /EHsc /Zi async.cpp && async 

Dla mnie to awarie programu. Podejrzewam, że istnieje limit liczby fizycznych kontraktów futures w tym samym czasie. Jeśli zmniejszę liczbę iteracji do kilku zamówień, to działa.

Więc dwa pytania:

  1. Czy istnieje limit faktycznie uruchomionych futures w C++ 11?

  2. Dlaczego ten kod w ogóle się zawiesza? Jeśli jawnie zrobię "get()" zaraz po "async()", to musi on ukończyć przyszłość przed kolejną iteracją, co oznacza, że ​​tylko jedna przyszłość biegnie jednocześnie.

UPDATE

mam uproszczony kod do:

#include <future> 

int main(int argc, char* argv[]) { 
    for (auto i = 0L; i < 1000000; ++i) { 
    auto f = std::async([](){ return 0; }); 
    f.get(); 
    } 
    return 0; 
} 

i nadal wywala mnie. Nie rzuca, sprawdziłem to. Ale teraz mam widoczny ślad stosu:

async.exe!_Mtx_unlock(_Mtx_internal_imp_t * * mtx) Line 229 C++ 
async.exe!std::_Mtx_unlockX(_Mtx_internal_imp_t * * _Mtx) Line 84 C++ 
async.exe!std::_Mutex_base::unlock() Line 47 C++ 
async.exe!std::unique_lock<std::mutex>::~unique_lock<std::mutex>() Line 284 C++ 
async.exe!std::_Associated_state<int>::_Set_value(int && _Val, bool _At_thread_exit) Line 358 C++ 
async.exe!std::_Packaged_state<int __cdecl(void)>::_Call_immediate() Line 569 C++ 
async.exe!std::_Async_state<int>::`std::U_Nil::ain::ain'::`3'::<lambda_A200A86DFF9A63A1>::operator()() Line 700 C++ 
[email protected]@[email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@QEAAXXZ() Line 420 C++ 
[email protected][email protected][email protected]<lambda_A200A86DFF9A63A1>@[email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected]@[email protected]@[email protected][email protected][email protected]<lambda_23AC5A2FBB53FD4D>@[email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@[email protected][email protected][email protected]@@[email protected]@[email protected]@[email protected]@@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@@[email protected]@UEAAXXZ() Line 217 C++ 
async.exe!std::_Func_class<void,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>::operator()() Line 1056 C++ 
async.exe!std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>::_ApplyX<Concurrency::details::_Unit_type>() Line 420 C++ 
async.exe!std::_Func_impl<std::_Callable_obj<`Concurrency::details::_MakeVoidToUnitFunc'::`3'::<lambda_25D33530A43E1C90>,0>,std::allocator<std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> >,Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::_Do_call() Line 217 C++ 
async.exe!std::_Func_class<Concurrency::details::_Unit_type,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::operator()() Line 486 C++ 
async.exe!`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B>::operator()() Line 325 C++ 
async.exe!Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> >::operator()() Line 72 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_InvokeBridge<Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > >(Concurrency::details::_PPLTaskHandle<`Concurrency::details::_Task_impl<Concurrency::details::_Unit_type>::_ScheduleTask'::`3'::<lambda_7D9BCD859405C05B> > * _PChore) Line 4190 C++ 
async.exe!Concurrency::details::_UnrealizedChore::_UnstructuredChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 275 C++ 
async.exe!Concurrency::details::_PPLTaskChore::_DeletingChoreWrapper(Concurrency::details::_UnrealizedChore * pChore) Line 78 C++ 
async.exe!Concurrency::details::InternalContextBase::ExecuteChoreInline(Concurrency::details::WorkItem * pWork) Line 1600 C++ 
async.exe!Concurrency::details::InternalContextBase::Dispatch(Concurrency::DispatchState * pDispatchState) Line 1704 C++ 
async.exe!Concurrency::details::FreeThreadProxy::Dispatch() Line 191 C++ 
async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain(void * lpParameter) Line 173 C++ 
kernel32.dll!0000000076df652d() Unknown 
ntdll.dll!0000000076f2c521() Unknown 

i wątków:

Unflagged  1864 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f518ca Normal 
Unflagged  10964 0 Main Thread Main Thread async.exe!do_signal Normal 
Unflagged  7436 0 Worker Thread ntdll.dll thread ntdll.dll!0000000076f52c1a Normal 
Unflagged  10232 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged > 10624 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!_Mtx_unlock Normal 
Unflagged  4756 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::ThreadProxy::SuspendExecution Normal 
Unflagged  11100 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!Concurrency::details::InternalContextBase::WaitForWork Normal 
Unflagged  6440 0 Worker Thread async.exe!Concurrency::details::ThreadProxy::ThreadProxyMain async.exe!std::vector<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64>,std::allocator<std::pair<void (__cdecl*)(void * __ptr64),void * __ptr64> > >::_Tidy Normal 

używam VS 11.0.40825.2 PREREL.

+3

Brzmi jak błąd kompilatora. –

+0

Nie wierzę, że ta inwokacja uruchamia inny wątek, jest to tylko opóźnione wykonanie. Np. Foo powinno zostać wywołane, gdy wykonywana jest linia f.get(). – alanxz

+1

Debugger powinien pomóc ci zrozumieć, dlaczego kod ulega awarii. Spróbuję tego, zanim założę, że kompilator jest zepsuty. –

Odpowiedz

4
  1. Oczywiście istnieją limity implementacji, tak jak istnieje limit na to, jak duża może być tablica. std :: async może zasygnalizować błąd "resource_unavailable_try_again", jeśli zasadą uruchamiania jest Lauch :: Async i system nie może uruchomić nowego wątku. Ale nie otrzymujesz tego błędu.

  2. Program nie powinien się zawieszać i nie działa dla mnie (VS11 x64, wersja wydania, to samo źródło i linia poleceń).

    Wierzę, że nawet bez .get() program nie będzie miał więcej niż jedną operację asynchroniczną od razu. Przypisujesz przyszłość do zmiennej lokalnej, a przyszłość jest niszczona w każdej iteracji pętli, zmuszając operację asynchroniczną do ukończenia przed uruchomieniem kolejnej w kolejnej iteracji pętli.

1

Spróbuj zamknąć swój kod w main() przy użyciu try-catch i sprawdź, czy generuje wyjątek std ::. To może dać wskazówkę. Poza tym C++ 11 w VS jest nadal wersją beta.

+6

A beta jest wtedy, gdy zgłoszenia błędów są najbardziej wartościowe. –

1
  1. Nie, normy nie określają ograniczeń dotyczących biblioteki obsługi wątków (zawierają wątek, przyszłość itp.).

  2. To zależy od jakości wykonania biblioteki obsługi wątków i bazowego interfejsu API.Jak mówisz, f.get() czeka na komplację zadań (to zachowanie wymaga standardu C++). Gdy implementacja biblioteki NIE może ponownie użyć zasobów, takich jak uchwyt wątku bazowego API, MOŻE spowodować brak systemu resouce i awarię programu. Jest to jakość implementacji biblioteki.

0

Jeśli używasz g ++ z opcją std = C++ 11, upewnij się, że masz najnowszą wersję i link do pthread.

Na przykład, na CodingGround domyślna kompilacji, które można dostać (za pomocą przycisku kompilacji) jest:

g++ -std=c++11 -o main *.cpp 

i nie jest on z "co(): Nieznany błąd -1". Ale można ręcznie dodać -lpthread do polecenia kompilacji:

g++ -std=c++11 -o main -lpthread *.cpp 

i będzie działać dobrze.