IT

packaged_task와 비동기의 차이점은 무엇입니까

lottoking 2020. 7. 19. 09:06
반응형

packaged_task와 비동기의 차이점은 무엇입니까


C ++ 11의 모델로 작업하는 동안

std::packaged_task<int(int,int)> task([](int a, int b) { return a + b; });
auto f = task.get_future();
task(2,3);
std::cout << f.get() << '\n';

auto f = std::async(std::launch::async, 
    [](int a, int b) { return a + b; }, 2, 3);
std::cout << f.get() << '\n';

정확히 같은 일을 할 것입니다. std::async와 함께 하면 차이가있을 수있는 경우 std::launch::deferred하나가 큰 실행입니까?

이 두 케이스에서 다른 의미의 차이점은 무엇이며, 더 중요한 것은 무엇입니까?


실제로 방금 제공 한 예는 다음과 같이 다소 긴 기능을 사용하면 차이점을 보여줍니다.

//! sleeps for one second and returns 1
auto sleep = [](){
    std::this_thread::sleep_for(std::chrono::seconds(1));
    return 1;
};

패키지 된 작업

A packaged_task는 자체적으로 시작되지도 않습니다.

std::packaged_task<int()> task(sleep);

auto f = task.get_future();
task(); // invoke the function

// You have to wait until task returns. Since task calls sleep
// you will have to wait at least 1 second.
std::cout << "You can see this after 1 second\n";

// However, f.get() will be available, since task has already finished.
std::cout << f.get() << std::endl;

std::async

반면 std::asynclaunch::async는 다른 스레드에서 작업을 실행하려고 시도합니다 .

auto f = std::async(std::launch::async, sleep);
std::cout << "You can see this immediately!\n";

// However, the value of the future will be available after sleep has finished
// so f.get() can block up to 1 second.
std::cout << f.get() << "This will be shown after a second!\n";

약점

그러나 async모든 것을 사용하기 전에 반환 된 미래에는 특별한 공유 상태가 있으므로 future::~future차단 해야 합니다.

std::async(do_work1); // ~future blocks
std::async(do_work2); // ~future blocks

/* output: (assuming that do_work* log their progress)
    do_work1() started;
    do_work1() stopped;
    do_work2() started;
    do_work2() stopped;
*/

따라서 실제 future상황이 바뀌면 결과를 유지해야합니다.

{
    auto pizza = std::async(get_pizza);
    /* ... */
    if(need_to_go)
        return;          // ~future will block
    else
       eat(pizza.get());
}   

이에 대한 자세한 내용은 허브 셔터의 문서를 참조 async하고~future , 문제를 설명하고, 스콧 마이어의 std::futures에서이 std::async특별하지 않은 게이트웨이를 설명한다. 또한이 동작 은 C ++ 14 이상에서 지정 일반적으로 C ++ 11 구현되었습니다.

추가 차이점

std::async혹시 사용 하면 더 이상 문구에서 std::packaged_task사용할 수 있습니다.

std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::thread myThread(std::move(task),2,3);

std::cout << f.get() << "\n";

또한를 packaged_task호출하기 전에를 호출해야합니다 f.get(). 그렇지 않으면 미래가 준비되지 않으므로 프로그램이 중단됩니다.

std::packaged_task<int(int,int)> task(...);
auto f = task.get_future();
std::cout << f.get() << "\n"; // oops!
task(2,3);

TL; DR

std::async어떤 일을 끝내고 싶고 끝났을 때별로 신경 쓰지 않고 std::packaged_task다른 스레드로 옮기거나 나중에 호출하기 위해 일을 마무리하고 싶을 사용하십시오 . 또는 Christian 을 인용합니다 .

결국 a std::packaged_task는 구현을위한 낮은 수준의 기능 일뿐입니다 std::async(이는 std::async같은 다른 낮은 수준의 항목과 함께 사용하는 것보다 더 많은 것을 할 수있는 이유입니다 std::thread). 간단히 말하면 a std::packaged_task는 a에 std::function연결되어 있고 a std::futurestd::async감싸고 호출합니다 std::packaged_task(아마도 다른 스레드에서).


패키지 작업 대 비동기

p> 패키지 작업에는 작업[function or function object]과 미래 / 약속 쌍이 있습니다. 작업이 반환 문을 실행하면됩니다set_value(..)packaged_task의 약속.

a> 주어진 Future, promise 및 package 작업은 스레드에 대해 너무 걱정하지 않고 간단한 작업을 생성 할 수 있습니다 [스레드는 작업을 실행하기 위해 제공하는 것입니다].

그러나 사용할 스레드 수 또는 작업이 현재 스레드 또는 다른 스레드에서 가장 잘 실행되는지 여부 등을 고려해야합니다 async(). 이러한 결정은 새 스레드를 만들지 또는 이전 스레드를 재활용 할지를 결정 하는 스레드 실행기에 의해 처리 될 수 있습니다. 하나 또는 단순히 현재 스레드에서 작업을 실행합니다. 미래를 반환합니다.


"클래스 템플릿 std :: packaged_task는 호출 가능한 대상 (함수, 람다 식, 바인드 식 또는 다른 함수 개체)을 래핑하여 비동기 적으로 호출 할 수 있도록합니다. 반환 값이나 throw 된 예외는 액세스 할 수있는 공유 상태에 저장됩니다. std :: future 객체를 통해. "

"템플릿 함수 async는 함수 f를 비동기 적으로 (잠재적으로 별도의 스레드에서) 실행하고 결국 해당 함수 호출의 결과를 보유 할 std :: future를 반환합니다."

참고 URL : https://stackoverflow.com/questions/18143661/what-is-the-difference-between-packaged-task-and-async

반응형