프로그래밍/Parallel Programming

병렬 프로그래밍 Parallel Programming - run-with-cancellation-token

nanze 2022. 1. 5. 17:27
반응형

이전 정리글

2022.01.05 - [프로그래밍/Parallel Programming] - 병렬 프로그래밍 Parallel Programming - task cancel

 

병렬 프로그래밍 Parallel Programming - task cancel

이전 정리글은 2022.01.05 - [프로그래밍/Parallel Programming] - 병렬 프로그래밍 Parallel Programming - cancellation_token 특성 병렬 프로그래밍 Parallel Programming - cancellation_token 특성 이전 정리..

nanze.tistory.com

이번 포스팅에 정리할 대상은 run_with_cancellation_token 이다.

run_with_cancellation_token

이 함수는 인자로 실행 함수와 취소 토큰을 받는다. 말 그대로 취소시킬 수 있는 토큰을 주면서 함수를 실행하는 것이다. 이 함수는 ppl 에서 제공하는 parallel_for 등의 함수를 실행 도중 취소시킬 때 유용하게 사용될 수 있다. 

다음 코드를 보자. 

#include <ppl.h>
#include <ppltasks.h>
#include <iostream>

using namespace std;
using namespace concurrency;

int main()
{
	cancellation_token_source token_src;
	cancellation_token token = token_src.get_token();
	combinable<int> total;


	run_with_cancellation_token(
		[&] {
		parallel_for(0, 100, [&](int i)
		{
			if (token.is_canceled()) {
				//cancel_current_task(); exception occured. try catch 외부 사용 가능
				return;
			}

			total.local() += 1;

			if (i == 55) {
				wcout << L"try to cancel." << endl;
				
				token_src.cancel();
			}
			else {
				wcout << L"parallel_for running. >> " << i  << endl;
				wait(200);
			}
		}
		);
	}
	, token);

	wcout << L"total call num : " << total.combine(plus<int>()) << endl;

	return 0;
}

위 코드 실행 결과는 parallel_for 동작이 다 수행되지 않고 중간에 탈출되는 것을 확인할 수 있다. parallel_for 내부에 일반적인 break 는 사용할 수 없으며 일반적인 반환을 할 경우에는 중간에 탈출하지 못하고 수행된다. 위와 같이 run_with_cancallation_token() 함수는 PPL 에서 제공하는 parallel_for 같은 함수 내부 탈출을 위해서 용이하게 사용된다. 

 

다음 코드도 한번 확인해보자.

#include <ppl.h>
#include <ppltasks.h>
#include <iostream>

using namespace std;
using namespace concurrency;

int main()
{
	cancellation_token_source token_src;
	cancellation_token token = token_src.get_token();
	combinable<int> total;


	structured_task_group tgrp;
	task_group_status st;
	st = tgrp.run_and_wait(
		[&] {
		parallel_for(0, 100, [&](int i)
		{

			if (tgrp.is_canceling()) {
				return;
			}

			total.local() += 1;


			if (i == 55) {
				wcout << L"try to cancel." << endl;
				
				tgrp.cancel();
			}
			else {
				wcout << L"parallel_for running. >> " << i  << endl;
				wait(200);
			}
		}
		);
	}
	);

	wcout << L"total call num : " << total.combine(plus<int>()) << endl;

	return 0;
}

위 코드는 이전 코드와 동일하지만 task_group 을 사용한 예이다. 위와 같은 방식들로 parallel_for 같은 함수들도 동작 중간에 나오는 것이 가능하다. 추가적으로 마지막 동작 콜 수치를 확인하면 전체가 동작하는지 중간에 탈출하는지 확인할 수 있다. 

 

 

반응형