CPU 오프로딩#
CPU 오프로딩 개요#
CPU 오프로딩은 모델에서 지원되지 않거나 NPU 실행에 적합하지 않은 부분을 CPU에 남기고, 나머지 지원되는 부분은 Mobilint NPU용으로 컴파일하는 기능입니다. 산출물은 여전히 MXQ 패키지이지만, 이를 실행하려면 런타임이 CPU 오프로딩 실행을 지원해야 합니다.
CPU 오프로딩은 모델 안에 작은 전처리, 후처리, 형상 처리, 인덱싱 연산이 있고 해당 연산이 NPU 실행에 적합하지 않을 때 유용합니다. 지원되지 않는 구간이 크거나 성능에 중요한 본문 구간 중간에 있으면 원본 모델을 수정하거나, 더 깔끔한 그래프로 내보내거나, NPU 본문 서브그래프만 컴파일하는 편이 좋습니다.
CPU 오프로딩은 컴파일 설정 또는 Python API에서 명시적으로 활성화합니다.
from qbcompiler import mxq_compile
mxq_compile(
model="model.onnx",
backend="onnx",
target_device="regulus-rb",
calib_data_path="./calib",
save_path="./model_cpu_offload.mxq",
cpu_offload=True,
)
컴파일 설정에서는 cpuOffload: true를 사용하고, 설치된 CLI가 해당 플래그를 제공하면 --cpu-offload를 사용할 수 있습니다.
디바이스에서 사용하는 런타임 버전이 CPU 오프로딩으로 컴파일된 MXQ 실행을 지원하는지 확인해야 합니다. CPU 오프로딩은 임의의 Python, PyTorch, TensorFlow, 사용자 코드 실행을 대체하지 않으며, 이 경로가 지원하는 연산 범위만 처리합니다.
지원되지 않는 연산자 처리#
parse 단계에서 qb Compiler는 원본 모델을 MBLT로 변환하고 선택한 target device에서 지원되는 레이어를 표시합니다. MXQ 생성 단계에서 CPU 오프로딩을 사용하면 그래프는 세 구간으로 나뉠 수 있습니다.
CPU head: NPU 실행 가능 구간 앞에 있는 CPU 실행 구간입니다.NPU body: NPU용으로 컴파일되는 연속된 본문 서브그래프입니다.CPU tail:NPU body뒤에 있는 CPU 실행 구간입니다. 대개 작업별 후처리입니다.
이 구조는 YOLO처럼 합성곱 백본과 neck은 NPU에 적합하지만 마지막 디코딩이나 필터링 로직에 지원되지 않는 연산자가 포함될 수 있는 모델에서 특히 유용합니다. 최종 컴파일 전에 Netron으로 MBLT를 열어 지원 레이어 구간을 확인할 수 있습니다.
지원되지 않는 연산자가 있다고 해서 항상 안전한 것은 아닙니다. CPU 오프로딩은 그래프 경계 주변의 단순 CPU 실행 구간에 적합합니다. 지원되지 않는 연산자가 NPU 본문을 여러 작은 구간으로 나누면 CPU/NPU 전송 비용이 커지고, 컴파일러가 실용적인 MXQ를 만들지 못할 수 있습니다.
캘리브레이션 데이터 형상 차이#
CPU 오프로딩을 사용하지 않는 경우 비전 모델은 보통 NPU 본문에 들어가는 전처리된 텐서로 캘리브레이션합니다. 많은 이미지 모델에서 이 텐서는 크기 변경, 자르기, 색상 변환, 스케일링, 정규화가 적용된 HWC 형식입니다.
CPU 오프로딩을 사용하면 CPU head가 컴파일 그래프에 남으므로 캘리브레이션 데이터는 원본 모델 입력 형상과 일치해야 합니다. 내보낸 원본 모델이 NCHW를 기대하면 캘리브레이션 텐서도 NCHW여야 합니다. 원본 모델이 전처리를 포함하고 원본에 가까운 NHWC 또는 uint8 입력을 기대하면 같은 형상과 데이터 타입으로 캘리브레이션합니다.
규칙은 다음과 같습니다.
NPU 본문만 컴파일: 캘리브레이션 데이터는 NPU 본문 입력과 일치합니다.
CPU 오프로딩 사용: 캘리브레이션 데이터는 원본 컴파일 모델 입력과 일치합니다.
전처리도 여전히 중요합니다. 캘리브레이션에 사용되는 수치 분포는 실제 추론 입력이 거치는 애플리케이션 전처리와 같아야 합니다. 원본 모델과 정확도가 다르면 양자화를 조정하기 전에 캘리브레이션 형상, 전처리 순서, 채널 순서, 정규화, 출력 해석을 먼저 확인합니다.