Skip to Content

비동기 추론·취소·동시성

실습복습
관련 기초 개념

개요

UI와 추론을 분리하고 취소·수명·오래된 결과를 안전하게 처리한다.

먼저 Tensor 수명과 RAII의 핵심 개념을 확인하세요.

핵심 개요

UI 스레드에서 모델 적재·긴 추론을 직접 수행하면 입력·화면 반응이 멈출 수 있습니다. 작업 큐와 워커를 사용하되 세션·입력·문서 상태의 수명을 명확히 관리합니다.

취소는 결과를 버리는 처리와 실제 연산 중단을 구분합니다. 늦게 도착한 결과가 최신 문서나 사용자의 새 요청을 덮지 않도록 작업 ID와 revision을 확인합니다.

필요한 용어

  • Generation ID: 어느 요청 세대의 결과인지 구별하는 식별자
  • 협력적 취소: 작업이 취소 상태를 확인하고 정해진 지점에서 중단하는 방식

작동 과정

  1. UI·작업·모델·문서의 소유권을 나눕니다.
  2. 요청 ID·revision·취소 토큰을 작업에 넣습니다.
  3. 완료 시 최신 요청·문서인지 확인한 뒤 결과를 적용합니다.

풀이 예제

아래 입력과 기록은 직접 만든 교육용 가상 자료입니다.

입력·조건

요청 1은 느리고 요청 2는 빨리 끝났습니다. 나중에 요청 1 결과가 도착했습니다.

판단·결과

최신 요청 ID와 다르면 1의 결과를 화면·문서에 적용하지 않습니다.

이렇게 판단한 이유

완료 순서가 사용자 의도 순서와 같지 않으므로 명시적인 최신성 검사가 필요합니다.

로컬 실행 예제

실행 파일 받기

C++17, g++ -std=c++17 -pthread -Wall -Wextra -Werror async_inference.cpp -o async_inference 후 ./async_inference

g++ -std=c++17 -pthread -Wall -Wextra -Werror async_inference.cpp -o async_inference ./async_inference
// C++17: synthetic computation; generation/revision guards discard stale results. #include <cassert> #include <future> #include <iostream> #include <memory> #include <vector> struct Result { int generation, revision; float value; }; int main() { auto input = std::make_shared<const std::vector<float>>(std::vector<float>{1,2,3}); auto launch = [input](int generation, int revision) { return std::async(std::launch::async, [input,generation,revision] { float total=0; for(float value:*input) total+=value; return Result{generation,revision,total}; }); }; auto old = launch(1,1); int currentGeneration=2, currentRevision=1; // User cancelled/replaced request 1. const auto stale=old.get(); // Test harness waits; a UI thread should poll or dispatch completion. const auto applicable = [&](Result r) { return r.generation==currentGeneration && r.revision==currentRevision; }; assert(!applicable(stale)); auto active = launch(2,1); const auto good=active.get(); assert(applicable(good) && good.value==6); ++currentRevision; assert(!applicable(good)); // Document changed before applying. std::cout << "PASS: input ownership, cancellation discard, success, stale document\n"; }

기대 결과: 입력 소유·취소 결과 폐기·성공·문서 변경 후 결과 거절

2026-10-21 로컬 환경에서 실행했습니다. 가상 자료·소형 CPU 예제의 동작 검사이며 실제 업무 모델의 품질·클라우드·GPU·Office 제품 연동 검증은 아닙니다.

흔한 실패와 복구

세션·실행 공급자의 동시 실행 지원을 확인하지 않고 공유 객체를 무제한 병렬 호출하지 않습니다. 사용하는 버전과 공급자에서 시험합니다.

확인 문제

늦게 끝난 오래된 요청 결과는?

  1. 항상 마지막 도착 결과로 덮어쓴다
  2. 현재 요청 ID·문서 revision을 확인해 적용 또는 폐기한다
  3. 문서가 닫혔어도 포인터로 접근한다

풀이 기록 기능을 불러오는 중…

해설 보기

정답: B. 현재 요청 ID·문서 revision을 확인해 적용 또는 폐기한다

현재 요청 ID·문서 revision을 확인해 적용 또는 폐기한다 세션·실행 공급자의 동시 실행 지원을 확인하지 않고 공유 객체를 무제한 병렬 호출하지 않습니다. 사용하는 버전과 공급자에서 시험합니다.

참고 자료

  1. ONNX Runtime: Ort::Session  — 세션 생성·입출력 정보·실행 계약.
  2. ONNX Runtime: Performance tuning  — 스레드·메모리·실행 공급자 성능 검토.

자료 확인: 2026-10-21. 사례·문항·실습은 자체 제작했습니다. 외부 서비스 호출과 실제 모델 품질 측정은 학습자가 별도 환경에서 수행합니다.

직접 적용하기

교육용 가상 상황

문서 분석 중 사용자가 파일을 닫거나 편집합니다. 취소·수명·완료 적용 조건을 설계하세요.

UI와 추론을 분리하고 취소·수명·오래된 결과를 안전하게 처리한다. 판단 근거와 검증할 결과를 적으세요.

답안 저장 기능을 불러오는 중…

검증 기준과 해설 보기
  1. 문서 포인터를 무조건 보존하지 않는다
  2. 요청·revision의 최신성을 확인한다
  3. 취소와 실제 연산 종료를 구분한다

작업은 필요한 입력 사본과 안전한 세션 수명을 소유합니다. 문서 닫기·새 편집은 작업 세대를 바꾸고 완료 적용 전에 문서 존재·요청 ID·revision을 검사합니다. API의 실제 취소 지원과 결과 폐기를 나누며 워커 종료를 UI에서 무한 대기하지 않도록 설계합니다.

복습하기

  1. 취소 버튼이 실제 연산 중단을 뜻하나요?
  2. Generation ID가 필요한 이유는?
  3. 워커 입력의 소유권은 어떻게 하나요?
답변 확인 기준
  1. 취소 버튼이 실제 연산 중단을 뜻하나요?

    결과 폐기와 런타임 중단 지원을 구분해야 합니다.

  2. Generation ID가 필요한 이유는?

    이전 요청 결과가 최신 상태를 덮지 않도록 하기 위해서입니다.

  3. 워커 입력의 소유권은 어떻게 하나요?

    작업 완료까지 유효한 소유 객체나 안전한 사본을 유지합니다.