TL;DR
TensorRT의 IProgressMonitor는 엔진 빌드 중에 phase_start·step_complete·phase_finish 세 콜백으로 중첩된 진행 상태를 보고하고 step_complete의 반환값으로 빌드 취소를 요청하는 단일 경계 역할을 하며 Python과 C++ 샘플을 통해 즉시 적용 가능한 구현 패턴을 제공한다. 구현은 멀티스레드 호출을 고려한 Lock 또는 mutex로 상태를 보호하고 atomic 플래그로 취소 요청을 전달하며 터미널에서는 ANSI 시퀀스로 중첩 진행 막대를 갱신하고 비상호작용형 전송에서는 구조화된 이벤트를 내보내야 한다. 통합은 IBuilderConfig에 모니터를 설정한 뒤 LSP 알림, Server-Sent Events, 에이전트 툴콜 청크 같은 기존 전송으로 렌더 출력을 보내고 monitor.requestCancel()을 통해 Ctrl-C·IDE 중지·HTTP cancel 등 외부 소스로부터 일관된 취소 처리를 실현한다. 취소는 step 경계에서만 적용되므로 긴 전술 탐색 단계에서는 응답 지연이 수초에서 수십 초가 될 수 있고 phase_finish가 예상보다 먼저 호출될 수 있으므로 이를 운영상 고려해야 한다.
빠른 이해
새로운 점
IProgressMonitor를 단일 경계로 삼아 터미널·IDE·HTTP·에이전트로 진행과 취소를 일관되게 연결한 실용적 통합 패턴
핵심 메커니즘
빌더가 phase_start로 단계 트리를 열고 각 step에서 step_complete를 호출하면 모니터가 현재 스텝을 갱신하고 Boolean을 반환해 계속할지 취소할지를 결정하며 phase_finish가 단계 종료를 정리하는 입력→처리→출력 흐름이다.
섹션별 상세
문제와 목적
IProgressMonitor 인터페이스와 동작 원리
- step_complete는 빌더의 동작을 변경하는 유일한 콜백으로, 반환값이 False이면 빌드 취소가 요청된다. — Table 1 및 관련 문단(인터페이스 설명)에서 메서드 의미와 취소 경로를 기술한 부분
Python 구현 핵심
import tensorrt as trt
from dataclasses import dataclass, field
from threading import Lock
@dataclass
class _PhaseState:
num_steps: int
current_step: int = 0
parent: str | None = None
class RichProgressMonitor(trt.IProgressMonitor):
def __init__(self):
super().__init__()
self._lock = Lock()
self._phases: dict[str, _PhaseState] = {}
self._cancelled = False
self._rendered_lines = 0
def phase_start(self, phase_name, parent_phase, num_steps):
with self._lock:
self._phases[phase_name] = _PhaseState(
num_steps=num_steps,
parent=parent_phase
)
self._render()
def step_complete(self, phase_name, step) -> bool:
with self._lock:
if phase_name in self._phases:
self._phases[phase_name].current_step = step
self._render()
return not self._cancelled
def phase_finish(self, phase_name):
with self._lock:
self._phases.pop(phase_name, None)
self._render()
TensorRT의 IProgressMonitor를 상속해 phase별 상태를 잠금으로 보호하며 추적하고 step_complete에서 취소 플래그를 검사하는 Python 구현 예시이다.
터미널 렌더링과 출력 처리
def _render(self):
# Order phases by nesting depth so children draw under parents.
rows = sorted(
self._phases.items(), key=lambda kv: (kv[1].parent or "", kv[0]),
)
# Move the cursor up by the number of lines the PREVIOUS render printed,
# not the current row count — phases are added on nesting and removed on
# phase_finish, so the two differ exactly when the tree changes shape.
if self._rendered_lines:
print(f"\x1b[{self._rendered_lines}A", end="")
for name, st in rows:
# step is a 0-based index in [0, num_steps); +1 turns it into a
# completed count so the bar can actually reach 100%.
done = min(st.current_step + 1, st.num_steps)
pct = done / max(st.num_steps, 1)
bar = "█" * int(40 * pct) + "·" * (40 - int(40 * pct))
indent = " " if st.parent else ""
print(f"\x1b[2K{indent}{name}", end="")
터미널에 중첩 진행 막대를 출력하기 위한 렌더러의 핵심 로직으로 행 정렬, 커서 이동, 진행률 바 계산을 포함한다.
C++ 구현 핵심
#include <unordered_map>
#include <mutex>
#include <atomic>
class RichProgressMonitor : public nvinfer1::IProgressMonitor {
public:
void phaseStart(char const* phaseName, char const* parentPhase, int32_t nbSteps) noexcept override {
std::lock_guard g(mu_);
phases_[phaseName] = {nbSteps, 0, parentPhase ? parentPhase : ""};
render();
}
bool stepComplete(char const* phaseName, int32_t step) noexcept override {
std::lock_guard g(mu_);
auto it = phases_.find(phaseName);
if (it != phases_.end()) it->second.current = step;
render();
return !cancelled_.load();
}
void phaseFinish(char const* phaseName) noexcept override {
std::lock_guard g(mu_);
phases_.erase(phaseName);
render();
}
void requestCancel() noexcept { cancelled_.store(true); }
private:
struct Phase { int32_t nbSteps; int32_t current; std::string parent; };
std::mutex mu_;
std::unordered_map<std::string, Phase> phases_;
std::atomic<bool> cancelled_{false};
void render() noexcept;
};
// Attach with:
// auto config = std::unique_ptr( builder->createBuilderConfig());
// RichProgressMonitor monitor; config->setProgressMonitor(&monitor);
C++에서 IProgressMonitor를 구현한 예시로, mutex로 상태를 보호하고 atomic 플래그로 취소 요청을 처리하는 구조이다.
외부 통합 경로
엣지 케이스와 운영상 주의점
시작 방법과 샘플 실행
용어 해설
- IProgressMonitor API(IProgressMonitor)
- — TensorRT 빌더가 엔진 빌드 진행 중에 호출하는 추상 콜백 인터페이스로, phase_start·step_complete·phase_finish 세 메서드를 오버라이드해 중첩된 진행 상태를 추적하고 step 경계에서 취소 신호를 전달하는 역할을 한다. 구현은 멀티스레드 호출을 고려한 동기화와 취소 플래그 처리, 렌더링 혹은 구조화된 이벤트 방출로의 변환을 포함한다. 이 인터페이스가 있으면 터미널·IDE·HTTP·에이전트 런타임으로 빌드 진행을 스트리밍하고 외부에서 안전하게 취소할 수 있다.
- 전략(타틱) 선택(Tactic Selection)
- — TensorRT 빌더가 엔진 최적화 과정에서 모델 연산을 실행할 하드웨어·커널·전략을 탐색하는 단계로, 개별 탐색 단계가 길어 취소 지연이 발생할 수 있다. 이 단계는 빌드 시간 변동의 주요 원인 중 하나이므로 진행 표시 및 단계별 취소 처리에서 핵심적으로 고려된다. 긴 단일 스텝은 취소 응답 시간에 수초에서 수십 초의 지연을 유발할 수 있다.
- ANSI 가상 터미널 제어문자(Virtual Terminal Escapes)
- — 터미널 커서를 이동하고 행을 지우는 제어 시퀀스로, 중첩 진행 막대를 실시간으로 갱신하기 위해 커서 이동([{n}A)과 행 삭제([2K)를 사용해 이전 렌더 출력 위치로 되돌리는 방식이 핵심이다. 렌더링 로직은 이전에 출력한 행 수를 기억해 커서를 올바르게 이동시켜야 하며, stdout 리다이렉션 시 제어문자가 로그를 오염시킬 수 있다. 상호작용형 터미널과 비상호작용형 전송(예: SSE)은 서로 다른 출력 전략이 필요하다.
- Language Server Protocol
- — IDE와 편집기 간의 표준화된 통신 규격으로, IProgressMonitor의 렌더 결과를 $/progress 알림과 같은 프로토콜 메시지로 변환해 IDE의 진행 표시창에 실시간으로 노출할 수 있다. 각 빌드 phase를 개별 토큰으로 취급하고 step_complete를 보고로 변환하면 IDE의 Stop 버튼이 모니터.requestCancel()을 호출해 빌드를 중단하게 만들 수 있다. LSP 전송은 상호작용형 클라이언트에 적합한 통합 경로다.
기술
- Python
- C++
- TensorRT
- Server-Sent Events
- Language Server Protocol
언급된 리소스
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.