코 루틴이란? C ++ 20?
"Parallelism2"또는 / 및 "Concurrency2"(아래 이미지 참조)와 어떤 점에서 다른가요?
아래 이미지는 ISOCPP에서 가져온 것입니다.
코 루틴이란? C ++ 20?
"Parallelism2"또는 / 및 "Concurrency2"(아래 이미지 참조)와 어떤 점에서 다른가요?
아래 이미지는 ISOCPP에서 가져온 것입니다.
답변:
추상적 인 수준에서 코 루틴은 실행 스레드를 갖는 아이디어에서 실행 상태를 갖는 아이디어를 분리합니다.
SIMD (단일 명령어 다중 데이터)에는 여러 "실행 스레드"가 있지만 실행 상태는 하나뿐입니다 (여러 데이터에서만 작동 함). 아마도 병렬 알고리즘은 하나의 "프로그램"이 다른 데이터에서 실행된다는 점에서 이와 비슷합니다.
스레딩에는 여러 "실행 스레드"와 여러 실행 상태가 있습니다. 둘 이상의 프로그램과 둘 이상의 실행 스레드가 있습니다.
코 루틴은 여러 실행 상태를 갖지만 실행 스레드를 소유하지 않습니다. 프로그램이 있고 프로그램에 상태가 있지만 실행 스레드가 없습니다.
코 루틴의 가장 쉬운 예는 다른 언어의 생성자 또는 열거 형입니다.
의사 코드에서 :
function Generator() {
for (i = 0 to 100)
produce i
}
이 Generator
라고하며 그것을 처음 호출이 반환됩니다 0
. 상태가 기억되고 (코 루틴의 구현에 따라 상태가 얼마나 달라지는 지) 다음에 호출 할 때 중단 된 지점에서 계속됩니다. 따라서 다음에 1을 반환합니다. 그런 다음 2.
마지막으로 루프의 끝에 도달하고 함수의 끝에서 떨어집니다. 코 루틴이 완성되었습니다. (여기서 일어나는 일은 우리가 말하는 언어에 따라 다릅니다. 파이썬에서는 예외가 발생합니다).
코 루틴은이 기능을 C ++로 가져옵니다.
코 루틴에는 두 종류가 있습니다. 스택 및 스택리스.
스택리스 코 루틴은 상태와 실행 위치에 로컬 변수 만 저장합니다.
스택 형 코 루틴은 스레드와 같은 전체 스택을 저장합니다.
스택리스 코 루틴은 매우 가볍습니다. 내가 읽은 마지막 제안은 기본적으로 함수를 람다와 같은 것으로 다시 작성하는 것과 관련이 있습니다. 모든 지역 변수는 객체의 상태가되며 레이블은 코 루틴이 중간 결과를 "생성"하는 위치로 /에서 점프하는 데 사용됩니다.
코 루틴은 협동 멀티 스레딩과 비슷하기 때문에 값을 생성하는 과정을 "수익"이라고합니다. 실행 지점을 호출자에게 다시 양보합니다.
Boost에는 스택 형 코 루틴이 구현되어 있습니다. 당신을 위해 항복하는 함수를 호출 할 수 있습니다. 스택 형 코 루틴은 더 강력하지만 더 비쌉니다.
코 루틴에는 단순한 생성기보다 더 많은 것이 있습니다. 유용한 방식으로 코 루틴을 구성 할 수있는 코 루틴에서 코 루틴을 기다릴 수 있습니다.
if, 루프 및 함수 호출과 같은 코 루틴은보다 자연스러운 방식으로 특정 유용한 패턴 (상태 머신과 같은)을 표현할 수있는 또 다른 종류의 "구조화 된 goto"입니다.
C ++에서 코 루틴의 특정 구현은 약간 흥미 롭습니다.
가장 기본적인 수준에서 C ++ :에 몇 가지 키워드 co_return
co_await
co_yield
와 함께 작동하는 일부 라이브러리 유형을 추가합니다.
함수는 본문에 하나를 포함하여 코 루틴이됩니다. 따라서 선언에서 그들은 함수와 구별 할 수 없습니다.
이 세 키워드 중 하나가 함수 본문에 사용되면 반환 유형 및 인수에 대한 표준 검사가 수행되고 함수가 코 루틴으로 변환됩니다. 이 검사는 함수가 일시 중단 될 때 함수 상태를 저장할 위치를 컴파일러에 알려줍니다.
가장 간단한 코 루틴은 생성기입니다.
generator<int> get_integers( int start=0, int step=1 ) {
for (int current=start; true; current+= step)
co_yield current;
}
co_yield
함수 실행을 일시 중단하고 해당 상태를에 저장 generator<int>
한 다음를 current
통해의 값을 반환 합니다 generator<int>
.
반환 된 정수를 반복 할 수 있습니다.
co_await
한편 한 코 루틴을 다른 코 루틴에 스플 라이스 할 수 있습니다. 하나의 코 루틴에 있고 진행하기 전에 기다릴 수있는 일 (종종 코 루틴)의 결과가 필요한 경우, 그 결과를 co_await
수행합니다. 준비가 되었으면 즉시 진행하십시오. 그렇지 않은 경우 대기중인 대기 가능 항목이 준비 될 때까지 일시 중지합니다.
std::future<std::expected<std::string>> load_data( std::string resource )
{
auto handle = co_await open_resouce(resource);
while( auto line = co_await read_line(handle)) {
if (std::optional<std::string> r = parse_data_from_line( line ))
co_return *r;
}
co_return std::unexpected( resource_lacks_data(resource) );
}
load_data
std::future
명명 된 리소스가 열릴 때 를 생성하고 요청 된 데이터를 찾은 지점까지 파싱 하는 코 루틴입니다 .
open_resource
및 read_line
s는 아마도 파일을 열고 파일에서 행을 읽는 비동기 코 루틴 일 것입니다. 는 co_await
의 중단과 준비 상태를 연결 load_data
진행 상황에.
C ++ 코 루틴은 사용자 공간 유형 위에 최소한의 언어 기능 세트로 구현 되었기 때문에 이보다 훨씬 더 유연합니다. 사용자 공간 유형은 효과적으로 의미co_return
co_await
와 co_yield
의미를 정의합니다. 사람들이 모나 딕 옵 셔널 표현식을 구현하는 데 사용하는 것을 보았습니다. 그러면 co_await
빈 옵 셔널이 자동으로 빈 상태를 외부 옵 셔널로 전파합니다.
modified_optional<int> add( modified_optional<int> a, modified_optional<int> b ) {
return (co_await a) + (co_await b);
}
대신에
std::optional<int> add( std::optional<int> a, std::optional<int> b ) {
if (!a) return std::nullopt;
if (!b) return std::nullopt;
return *a + *b;
}
;;
.
코 루틴은 다른 루틴이 완료 될 때까지 "대기"하고 일시 중지, 일시 중지, 대기, 루틴이 계속 진행되는 데 필요한 모든 것을 제공 할 수있는 (C ++에서) 함수 여야합니다. C ++ 사람들에게 가장 흥미로운 기능은 코 루틴이 이상적으로 스택 공간을 차지하지 않는다는 것입니다 ... C #은 이미 await 및 yield로 이와 같은 작업을 수행 할 수 있지만 C ++를 다시 빌드해야 할 수 있습니다.
동시성은 관심사가 프로그램이 완료해야하는 작업 인 관심사 분리에 중점을 둡니다. 이러한 우려의 분리는 여러 가지 방법으로 달성 될 수 있습니다. 일반적으로 일종의 위임입니다. 동시성의 개념은 여러 프로세스가 독립적으로 실행될 수 있고 (관심의 분리) '청취자'가 분리 된 관심사에 의해 생성 된 모든 것을 이동해야하는 곳으로 지시한다는 것입니다. 이것은 일종의 비동기 관리에 크게 의존합니다. Aspect 지향 프로그래밍 및 기타를 포함하여 동시성에 대한 많은 접근 방식이 있습니다. C #에는 아주 잘 작동하는 '대리자'연산자가 있습니다.
병렬 처리는 동시성처럼 들리며 관련 될 수 있지만 실제로는 코드의 일부를 실행되고 결과가 다시 수신되는 다른 프로세서로 코드의 일부를 보낼 수있는 소프트웨어와 다소 병렬 방식으로 배열 된 많은 프로세서를 포함하는 물리적 구조입니다. 동 기적으로.