Ultralytics YOLO27: 대기자 명단에 등록하세요.
Get Started
강의중급

CPU에서 OpenVINO 사용

FP32, FP16, INT8 OpenVINO 모델을 내보내고 각각을 검증한 다음, 사용 중인 CPU에서 효과가 있는 경우에만 INT8을 유지하세요.

이미 보유한 Intel CPU로 GPU 인스턴스를 대체할 수 있는 경우가 많습니다. Ultralytics 벤치마크에서 YOLO26m은 PyTorch의 192ms에서 노트북 Core Ultra CPU의 OpenVINO INT8 사용 시 36ms로 단축됩니다. 다만 성능 향상은 칩에 따라 달라지며, 이 강의의 ARM 테스트 노트북에서는 이미지 4장으로 캘리브레이션한 INT8 내보내기로 mAP가 3포인트 하락했습니다. 배포 전에 어떤 경우에 해당하는지 측정하는 방법을 알아봅니다.

학습 성과

FP32, FP16, INT8 OpenVINO 모델을 내보내고, 사용 중인 CPU에서 정확도와 속도를 비교한 다음, 선택 이유를 문서화하세요.

속성 과정
이미 사용법을 알고 계신다면, 간단히 요약해 드리겠습니다.
  1. yolo export model=yolo26n.pt format=openvino은 yolo26n_openvino_model/을 기록합니다.

  2. FP16(quantize=16)은 파일 크기를 절반으로 줄이지만 대부분의 CPU에서 FP32와 동일한 속도로 실행됩니다. INT8(quantize=8 data=your.yaml)은 Intel CPU에서 속도를 높여줍니다.

  3. 추론 시 Intel 장치를 선택하세요. device="intel:cpu", "intel:gpu" 또는 "intel:npu"입니다.

  4. 다음 내보내기에서 폴더를 덮어쓰기 전에 각 정밀도를 검증하고, 타깃에서 ONNX Runtime과 비교해 벤치마크하세요.

실습형

OpenVINO의 이점#

OpenVINO 에코시스템: PyTorch, TensorFlow, Keras, TensorFlow Lite, ONNX, JAX, PaddlePaddle의 모델을 OpenVINO를 통해 Intel CPU(및 ARM), Intel GPU, Intel NPU, FPGA에서 실행할 수 있으며 Windows, Linux, macOS를 지원합니다

OpenVINO는 PyTorch 및 ONNX 모델을 가져와 단일 API를 통해 Intel CPU, 내장형 및 외장형 GPU, NPU에서 실행합니다. CPU 커널은 Intel 명령어 세트(AVX2, AVX-512, AMX)를 대상으로 하며, INT8 경로도 성숙해 있습니다. CPU 열의 ARM 타일에 유의하세요. OpenVINO는 ARM에서도 실행되지만 커널은 Intel에 맞게 튜닝되어 있으므로, ARM에서 사용하기 전에 성능을 측정하세요.

Intel Core Ultra 7 155H CPU에서 공개된 벤치마크 결과(COCO128):

모델PyTorch FP32OpenVINO FP32OpenVINO INT8FP32 → INT8 mAP50-95
YOLO26n33.19 ms13.43 ms11.40 ms0.4734 → 0.4611
YOLO26s70.92 ms36.16 ms15.54 ms0.5632 → 0.5471
YOLO26m192.45 ms102.52 ms35.72 ms0.6191 → 0.6025

이 표에서 세 가지 원칙을 도출할 수 있습니다.

  • Intel CPU에서는 OpenVINO FP32만으로도 PyTorch의 지연 시간이 대략 절반으로 줄어듭니다. 먼저 이 방법을 적용하세요.
  • 모델이 클수록 INT8의 효과가 커집니다. n은 1.2배, m은 2.9배 빨라지는 대신 mAP가 1.2~1.7포인트 하락합니다. n에서는 정확도 손실을 감수하고 INT8을 적용할 가치가 거의 없습니다.
  • 하드웨어를 구매하기 전에 내장 GPU를 사용해 보세요. 같은 칩의 Arc iGPU(device="intel:gpu")는 YOLO26n FP32를 9.13ms, YOLO26m을 34.47ms에 실행했습니다.

사용 중인 CPU에서 정밀도별 성능 비교#

각 정밀도를 내보내고 바로 검증한 후 다음 정밀도를 내보내세요.

from ultralytics import YOLO

if __name__ == "__main__":  # validation starts worker processes on macOS and Windows
    model = YOLO("yolo26n.pt")  # or runs/detect/pills_v1/weights/best.pt
    for name, quantize in (("FP32", None), ("FP16", 16), ("INT8", 8)):
        path = model.export(format="openvino", quantize=quantize, data="coco8.yaml")  # or my_dataset/data.yaml
        m = YOLO(path).val(data="coco8.yaml", batch=1, plots=False, verbose=False)  # before the next export overwrites it
        print(f"{name}: mAP50-95 {m.box.map:.4f}  -> {path}")
OpenVINO: export success ✅ 2.3s, saved as 'yolo26n_openvino_model/' (9.6 MB)
FP32: mAP50-95 0.6783  -> yolo26n_openvino_model/
OpenVINO: export success ✅ 1.6s, saved as 'yolo26n_openvino_model/' (5.1 MB)
FP16: mAP50-95 0.6783  -> yolo26n_openvino_model/
WARNING ⚠️ OpenVINO: >300 images recommended for INT8 calibration, found 4 images.
OpenVINO: export success ✅ 11.3s, saved as 'yolo26n_int8_openvino_model/' (3.2 MB)
INT8: mAP50-95 0.6460  -> yolo26n_int8_openvino_model/

각 줄에서 확인할 수 있는 내용:

  • FP32와 FP16의 점수는 동일하고 FP16의 크기는 절반(5.1MB 대 9.6MB)이지만, 두 모델이 같은 폴더에 기록되었습니다. 두 모델을 모두 먼저 내보낸 다음 나중에 검증했다면 FP16을 두 번 측정했을 것입니다.
  • INT8의 크기는 3.2MB이며 정확도가 3.2포인트 하락했습니다. COCO8의 이미지 4장으로 캘리브레이션했기 때문입니다. 경고 메시지도 이를 알려줍니다. 실제 캘리브레이션에는 자체 YAML(fraction은 사용할 이미지 수를 제한함)에 지정된 실제 운영 환경과 유사한 이미지 수백 장이 필요합니다.
  • 이 측정으로는 속도를 알 수 없습니다. 속도는 아래의 벤치마크를 사용해 측정하세요.

내보낸 모델을 특정 Intel 장치에서 실행하려면 다음을 따르세요.

from ultralytics import YOLO

ov_model = YOLO("yolo26n_openvino_model/")
results = ov_model("https://ultralytics.com/images/bus.jpg", device="intel:cpu")  # or intel:gpu, intel:npu

전체 폴더를 배포하세요. yolo26n.xml(그래프), yolo26n.bin(가중치), metadata.yaml입니다. intel:gpu과 intel:npu는 Intel 하드웨어가 필요합니다.

ONNX Runtime과 비교해 실행 시간 측정#

정확도는 확인했으므로, 실제로 처리할 부하를 적용한 상태에서 타깃 장치의 속도를 측정해야 합니다. 첫 번째 강의의 pick_runtime.py을 CANDIDATES = ("onnx", "openvino")과 함께 실행하세요. 다른 작업이 CPU를 함께 사용하는 Apple 실리콘 테스트 노트북에서 측정한 결과는 다음과 같습니다.

onnx      p50  30.0 ms  p95  46.4 ms  misses the 30 ms budget
openvino  p50  22.8 ms  p95 113.5 ms  misses the 30 ms budget

OpenVINO는 중앙값은 더 좋았지만 꼬리 지연 시간은 훨씬 나빴습니다. Ultralytics 래퍼는 LATENCY 힌트(로그에 Using OpenVINO LATENCY mode for batch=1 inference on CPU으로 표시됨)를 사용해 OpenVINO를 컴파일하여 각 요청을 CPU 코어 전반에 분산합니다. 다른 작업이 같은 코어를 사용하면 가장 느린 요청의 지연 시간이 특히 커집니다. 전용 Intel 장치에서는 대개 위의 공개 벤치마크와 비슷한 결과가 나오지만, 실제 p95는 자체 측정으로만 확인할 수 있습니다.

결정 규칙:

주의할 점#

FP16으로 CPU 속도가 빨라질 것이라고 기대하기

증상: FP16 내보내기 파일은 크기가 절반이지만 속도는 전혀 빨라지지 않습니다. 해결 방법: 대부분의 CPU에서 플러그인은 자체적으로 실행 정밀도를 선택합니다. 다운로드 용량을 줄이려면 FP16을 사용하고, 속도를 높이려면 INT8 또는 iGPU를 사용합니다.

모든 내보내기가 끝난 뒤 검증하기

증상: FP32와 FP16이 같은 파일이어서 동일한 수치가 보고됩니다. 해결 방법: FP32와 FP16 내보내기는 *_openvino_model/ 폴더를 공유하므로, 내보내기 직후 검증하거나 폴더 이름을 변경합니다.

유휴 시스템 벤치마크하기

증상: 평균은 괜찮아 보이지만 부하가 큰 순간에는 여전히 프레임이 누락됩니다. 해결 방법: 프로덕션 부하가 실행되는 상태에서 추론 시간을 측정하고, 평균이 아닌 p95를 기준으로 판단합니다. 한 서버에서 여러 스트림을 처리하려면 지연 시간 및 처리량 모드 가이드에 나온 것처럼 OpenVINO 런타임으로 .xml을 직접 로드해 THROUGHPUT 힌트와 함께 컴파일합니다.

검증을 수행하는 스크립트 보호하기

macOS와 Windows에서는 검증을 시작할 때 작업자 프로세스가 생성되며, 이 프로세스는 스크립트를 다시 임포트합니다. if __name__ == "__main__":이 없으면 이 강의의 테스트 실행에서 해당 작업자 프로세스들이 내보내기를 반복해 몇 분을 낭비하고, 측정하려던 CPU 자원을 놓고 경쟁했습니다.

사용해 보기

타깃 CPU에서 자체 모델과 데이터셋 YAML을 사용해 ov_compare.py을 실행한 다음, 운영 부하(또는 이를 모사한 부하)를 적용한 상태에서 ONNX와 OpenVINO를 사용해 pick_runtime.py을 실행하세요. 정밀도 또는 런타임, mAP50-95, 모델 크기, p95(ms)를 포함한 짧은 표와 배포할 모델을 밝히는 한 문장을 작성하세요.

완료 조건
다음 조건을 모두 충족하면 레슨을 완료한 것입니다.
  • 동일한 데이터에서 동일한 모델의 FP32, FP16, INT8 OpenVINO 내보내기를 검증했습니다.

  • 실제와 유사한 부하에서 동일한 머신으로 측정한 p95 OpenVINO 및 ONNX Runtime 지연 시간이 있습니다.

  • 정밀도와 런타임 선택 시 mAP 손실 비용과 측정한 속도 향상을 명시합니다.

정답 보기
python ov_compare.py    # accuracy and size of FP32, FP16, INT8
python pick_runtime.py  # p50 and p95 for ONNX Runtime and OpenVINO

위의 Core Ultra 7 155H 수치를 사용한 의사 결정 예시:

옵션mAP50-95규모이미지당 ms
OpenVINO FP320.47349.6 MB13.43
OpenVINO INT80.46113.2 MB11.40
iGPU FP32 (intel:gpu)0.47589.6 MB9.13

통합 GPU에서 OpenVINO FP32를 배포합니다. 가장 빠른 옵션이며 성능 손실이 없습니다. 반면 CPU에서 INT8을 사용하면 2ms를 절약하는 대신 1.2포인트의 손실이 발생합니다. YOLO26m 배포에서는 1.7포인트의 손실이 허용 범위 내라면 CPU INT8이 2.9배 더 빠르므로 선택이 달라집니다.

다음 단계

단일 프레임의 탐지는 기본 구성 요소입니다. 다음은 추적입니다. 추적을 사용하면 탐지 결과가 안정적인 ID를 가진 지속적인 객체로 바뀝니다.