C++/STL

[C++] std::async. launch policy

sseram 2023. 4. 20. 00:04
반응형

C++11 ~

 

 

 

C++ 에서 비동기 작업을 하기 위해 만들어진 library.

future을 include 하여 사용 가능하다.

 

 

C++에서 비동기 작업을 수행하는 또다른 library인 thread와의 차이는

 

https://donot-simsim.tistory.com/35

 

[C++] std::async, std::thread (1)

둘 다 비동기 작업을 수행하기 위해 만드는 것은 동일. 다만 몇 가지의 차이는 있다. 쓰면서 가장 와닿았던 두 가지의 특성이 있는데, 1. std::thread는 그저 thread를 하나 만들 뿐이다. 그에 관한 관

donot-simsim.tistory.com

 

https://donot-simsim.tistory.com/37

 

[C++] std::async, std::thread (2)

https://donot-simsim.tistory.com/35 [C++] std::async, std::thread (1) 둘 다 비동기 작업을 수행하기 위해 만드는 것은 동일. 다만 몇 가지의 차이는 있다. 쓰면서 가장 와닿았던 두 가지의 특성이 있는데, 1. std::t

donot-simsim.tistory.com

요렇다.

 

 

 

 

async 사용 시엔 두 개의 launch policy를 줄 수 있다.

 

 

launch::async는 

- 만들자마자 비동기적으로 실행된다.

- 소멸되기 전, 해당되는 작업이 다 끝날 때까지 기다린다.

 

launch::deferred는

- 만들어도 실제로 해당 future object로부터 get 하기 전까진 아무일도 하지 않는다.

- 만든 후에 해당 future로 아무것도 하지 않으면 바로 소멸된다.

 

 

 


 

 

먼저 launch::async.

#include <iostream>
#include <future>

using namespace std;

void asyncFunc(const string& msg) {

	cout << msg << endl;
	this_thread::sleep_for(chrono::seconds(5));

	cout << "async out" << endl;
}

int main()
{
	{
		auto a1 = async(launch::async, asyncFunc, "launch with async");
	}

	{
		auto a2 = async(launch::async, asyncFunc, "launch with async");
	}

	{
		auto a3 = async(launch::async, asyncFunc, "launch with async");
	}


	return 0;
}

위의 코드를 실행하면

 

 

위처럼 결과가 나온다.

 

a1, a2, a3를 각각의 {} 로 감싼 상태이다.

괄호를 나갈 때 내부에 있는 변수들을 전부 소멸시키고 나간다.

만약 a1을 무시하고 그냥 나갔다면 출력이 순차적으로 나오지 않을 텐데, 소멸 될 때 각각의 asyncFunc들이 전부 끝날 때 까지 기다리느라 위처럼 출력이 나오게 되었다.

 

 

 

 

반면 launch::deferred는

 

#include <iostream>
#include <future>

using namespace std;

void asyncFunc(const string& msg) {

	cout << msg << endl;
	this_thread::sleep_for(chrono::seconds(5));

	cout << "deferred out" << endl;
}

int main()
{
	{
		auto a1 = async(launch::deferred, asyncFunc, "a1 launch with deferred");
	}

	{
		auto a2 = async(launch::deferred, asyncFunc, "a2 launch with deferred");
	}

	{
		auto a3 = async(launch::deferred, asyncFunc, "a3 launch with deferred");
	}


	return 0;
}

 

아무것도 나오지 않는다.

deferred를 policy로 주면 해당 값을 얻어올 때 까지 함수의 실행을 미루게 된다. 그러다 보니 future object를 넘겨도 asyncFunc이 바로 실행되지 않고, 소멸 될 때 실행되고 있는 함수가 아무것도 없으니 빠르게 사라진다.

 

 

 


	{
		auto a2 = async(launch::deferred, asyncFunc, "a2 launch with deferred");
		a2.get();
	}

다만 코드를 살짝 바꿔서, 중간에 a2.get()을 넣으면

 

 

 

이런 식으로, get을 한 부분만 asyncFunc을 돌게 된다.

 

 

 

 

 

만들자마자 바로 돌게끔. thread처럼 쓰고 싶다

 -> launch::async

 

만들어 두고, 필요할 떄 사용하고 싶다

 -> launch::deferred.

 

 


 

 

참고로, async를 생성할 때 아무런 옵션도 주지 않으면

std::launch::async | std::launch::deferred 라는 policy를 준 것처럼 동작한다고 한다.

 

 

async, deferred 두 개의 정책을 동시에 주면 어떻게 되나 궁금해서 찾아봤는데

 

 

이러한 공식 문서와

더보기

Chapter 30.6.8 of ISO IEC 14882-2011 

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf

[ Note: If this policy is specified together with other policies, such as when using a policy value of launch::async | launch::deferred, implementations should defer invocation or the selection of the policy when no more concurrency can be effectively exploited. — end note ]

 

 

 

이런 글이 있더라.

 

 

 

 

 

결국 보면, 사용할 수 있는 cpu core가 있다면 async 로 돌리고, 그렇지 않다면 deferred로 알아서 정책을 선택한다고 하는 듯 하다.

 

그러니.. 엥간하면 정책을 정해서 async를 사용하도록 하자.

 

 

 

 

 

*잘못된 정보는 알려주시면 감사히 수정하겠습니다.

반응형