2017-11-30 5 views
3

내가 이해하는대로 std :: async의 일반적인 구현은 미리 할당 된 스레드 풀의 스레드에 대해 이러한 작업을 예약합니다.장기 실행 표준 : : 비동기는 다른 표준 : : 비동기를 굶주릴 수 있습니까?

그래서 먼저 스레드 풀에서 모든 스레드를 채우려면 충분히 오래 실행하여 충분한 시간 (예 : std::async)을 만들고 예약하십시오. 나중에 (실행이 끝나기 전에) 나는 단기간에 얼마간의 짧은 실행 시간을 만들어서 일정을 잡습니다. 단기 실행 엔진 중 적어도 하나가 완료 될 때까지 단기 실행 엔진이 전혀 실행되지 않을 수 있습니까? 아니면 표준 (특히 C++ 11)에서 이런 종류의 상황을 방지하는 보증이 있습니까 (OS가 라운드 로빈 방식으로 일정을 잡을 수 있도록 더 많은 스레드를 생성하는 것과 같은)?

+1

구현에 따라 다릅니다. C++ 표준이나 특정 구현에 대해 묻고 있습니까? –

+1

이상적으로는 표준의 보증을 원합니다. 하지만 당신은 그런 보장이 없다고 말하는 것 같아서, 나는 GCC의 libstdC++ (GCC 5.4, 그 것이 중요하다면)의 행동에 특별히 관심이있다. – Dreamer

답변

2

표준을 읽

출시 :: 비동기이 정책에서 설정되어있는 경우 [futures.async#3.1, 호출 INVOKE(DECAY_­COPY(std​::​forward<F>(f)), DECAY_­COPY(std​::​forward<Args>(args))...) ([func.require], [thread.thread.constr]) 에서 마치 비동기 호출 스레드에서 평가되는 DECAY_COPY에 대한 호출로 스레드 오브젝트가 나타내는 새로운 실행 스레드. [...] async()​async 발사 정책을 호출 할 때

그래서, 로-경우 규칙에 따라, 새로운 스레드를 양산해야합니다. 물론, 구현은 내부적으로 쓰레드 풀을 사용할 수 있지만, 일반적인 쓰레드 생성 오버 헤드를 제외하고, 특별한 '배고픈'것은 일어나지 않을 수 있습니다. 게다가, 스레드 로컬 환경의 초기화와 같은 일이 항상 일어나야합니다.

사실, 그 소리의 libC++ 트렁크 비동기 구현을 읽습니다 당신이 볼 수있는

unique_ptr<__async_assoc_state<_Rp, _Fp>, __release_shared_count> 
     __h(new __async_assoc_state<_Rp, _Fp>(_VSTD::forward<_Fp>(__f))); 

VSTD::thread(&__async_assoc_state<_Rp, _Fp>::__execute, __h.get()).detach(); 

return future<_Rp>(__h.get()); 

, 더 '명시 적'스레드 풀은 내부적으로 사용되지 않습니다.

here도 읽을 수 있으므로 gcc 5.4.0을 사용하는 libstdC++ 구현은 일반 스레드를 호출하기 만하면됩니다.

+1

정책이'launch :: async | launch :: deferred' (기본값) 구현은 – Caleth

+0

중 하나를 선택할 수 있습니다. @Caleth, 예, 나는 launch :: async 호출과 관련된 질문을 전제로 삼았습니다 (그렇지 않으면, 질문은별로 의미가 없을 것입니다). BTW, 구현도 제공하는 시작 정책이 있습니다. –

0

예, MSVC의 std::async은 최소한 MSVC2015 이상으로 해당 속성을 갖고있는 것 같습니다.

2017 년 업데이트에서 수정했는지 알 수 없습니다.

이것은 표준의 정신에 위배됩니다. 그러나 표준은 스레드 전달 진행 보장 (C++ 14 이상)에 대해서는 매우 모호합니다. 따라서 std::asyncstd::thread을 감싸는 것처럼 행동해야하지만 std::thread 진행 과정에 대한 보장은 충분히 약해서 as-if 규칙에서 보장 할 수 없습니다. 실제로

, 이것은 그런 문제가 나타나지 않습니다 MSVC2015에서 std::thread의 원료 사용으로, std::thread 원시 호출 내 스레드 풀 구현에 std::async를 대체하는 저를 주도하고있다.

나는 (작업 큐와) 스레드 풀은 std::async 또는 std::thread 중 원시 통화보다 훨씬 더 실용적인 것을 발견하고는 std::thread 또는 std::async 중 하나와 스레드 풀을 작성하는 정말 쉽기 때문에, 나는 좋을 걸 std::thread와 함께 하나를 쓰십시오.

스레드 풀은 std::async처럼 반환 할 수 있습니다 (풀 자체는 스레드 수명을 관리하므로 파괴 기능에는 자동 차단 기능이 없습니다).

나는 C++ 17이 더 나은 진행 보증을 추가했다는 것을 읽었지만 MSVC의 행동이 현재 표준 요구 사항에 위배되는지 결론을 내리기에 충분한 이해가 부족합니다.

+0

* "std :: thread forward 진행에 ​​대한 보장은 충분하지 않아서 이것이 as-if 규칙에 대한 보장이 아닙니다."* 나는 아닙니다. 이것이 확실한가? 표준의 편지는 비동기의 관찰 가능한 효과가 새로운 실행 스레드의 효과라고 말합니다. 반대로 MSVC 구현에서 실행되는 프로그램은 async() 호출이 동등한 스레드 호출과 다르게 동작한다는 관찰 가능한 증거를 수집 할 수 있습니다 (스레드 실행 진행 보증의 * 예외적 인 * 발생). –

+0

@MassimilianoJanes 표준을 제외하고 *는'std :: thread'가 합리적으로 * 작동한다는 것을 보증하지 않습니다. 'std :: thread'가 동작한다는 표준 보증과 다르게 동작하지 않습니다. 추상 기계 동작 이외의 방식으로 만 동작이 다릅니다. 관찰 가능한 행동은 "이 표준에서 요구하는 추상적 인 기계 및 행동 측면에서"의미를 가져야합니다. 스택 추적을하는 경우와 같이 다른 것들은 분명히 동일 할 수 없습니다. 결과적으로 underspecified forward progress 보장은'std :: thread'가'async'와 마찬가지로 나쁘다는 것을 의미합니다 ... – Yakk

+0

예, "thread (foo) .detach(); bar();"* * as-if 규칙에 따라 "thread (foo) .join(); bar()로 동작하지만 아직이 두 코드가 as-if 규칙과 동등한 것으로 결론 내릴 수 있습니까? –