Chapter 8 6 / 10

엣지 디바이스 선택

NVIDIA Jetson, Intel NCS, Google Coral TPU, 산업용 IPC 비교 분석과 애플리케이션별 최적 디바이스 선정 가이드

1엣지 AI 디바이스 생태계

제조 현장의 엣지 AI 구현을 위해 다양한 하드웨어 플랫폼이 존재합니다. 각 플랫폼은 연산 성능, 전력 효율, 소프트웨어 생태계, 가격 등에서 서로 다른 특성을 가지며, 애플리케이션 요구사항에 따라 최적의 선택이 달라집니다.

NNVIDIA Jetson

GPU 기반 고성능 엣지 AI 플랫폼. CUDA 생태계 지원

275 TOPS TensorRT CUDA

IIntel NCS/OpenVINO

VPU 기반 저전력 추론 가속기. x86 호환성 우수

4 TOPS OpenVINO 저전력

GGoogle Coral TPU

Edge TPU 기반 초저전력 추론. TFLite 최적화

4 TOPS TFLite 2W

산업용 IPC

확장 안정성 중심의 산업용 컴퓨터. 다양한 I/O 지원

넓은 온도 산업 인증 이중화

디바이스 선택 시 성능(TOPS)뿐 아니라 실제 워크로드에서의 처리량(FPS), 전력 효율(TOPS/W), 소프트웨어 성숙도를 종합적으로 평가해야 합니다.

2NVIDIA Jetson 시리즈

NVIDIA Jetson은 제조 현장에서 가장 널리 사용되는 엣지 AI 플랫폼입니다. GPU 아키텍처 기반으로 CUDA, cuDNN, TensorRT 등 풍부한 소프트웨어 스택을 제공합니다.

NVIDIA Jetson Product Lineup
Jetson Nano
Performance:472 GFLOPS
Power:5-10W
GPU:Maxwell
RAM:4GB
Entry/Education
Prototyping
Jetson Xavier NX
Performance:21 TOPS
Power:10-20W
GPU:Volta
RAM:8GB
Mid-tier Inference
Single Stream
Jetson Orin Nano
Performance:40 TOPS
Power:7-15W
GPU:Ampere
RAM:8GB
High Efficiency
Multi-stream
Jetson AGX Orin
Performance:275 TOPS
Power:15-60W
GPU:Ampere
RAM:32-64GB
High Performance
Multi-model
import subprocess
import json
from dataclasses import dataclass
from enum import Enum

class JetsonModel(Enum):
    NANO = "nano"
    XAVIER_NX = "xavier_nx"
    ORIN_NANO = "orin_nano"
    AGX_ORIN = "agx_orin"

class JetsonDeviceManager:
    """Jetson 디바이스 관리 및 모니터링"""

    SPECS = {
        JetsonModel.NANO: {"tops": 0.5, "power": [5, 10], "ram": 4},
        JetsonModel.XAVIER_NX: {"tops": 21, "power": [10, 20], "ram": 8},
        JetsonModel.ORIN_NANO: {"tops": 40, "power": [7, 15], "ram": 8},
        JetsonModel.AGX_ORIN: {"tops": 275, "power": [15, 60], "ram": 64}
    }

    def __init__(self, model: JetsonModel):
        self.model = model
        self.specs = self.SPECS[model]

    def get_power_mode(self) -> dict:
        """현재 전력 모드 조회"""
        result = subprocess.run(
            ["nvpmodel", "-q"],
            capture_output=True, text=True
        )
        return self._parse_nvpmodel(result.stdout)

    def set_power_mode(self, mode: int):
        """전력 모드 설정 (0=MAX, 1=보통, 2=저전력)"""
        subprocess.run(["sudo", "nvpmodel", "-m", str(mode)])

    def get_gpu_utilization(self) -> dict:
        """GPU 사용률 조회 (tegrastats 파싱)"""
        result = subprocess.run(
            ["tegrastats", "--interval", "100"],
            capture_output=True, text=True, timeout=1
        )
        return self._parse_tegrastats(result.stdout)

    def estimate_inference_fps(self, model_tops: float) -> float:
        """모델 연산량 기반 추론 FPS 추정"""
        # 실제 효율은 이론치의 60-80%
        efficiency = 0.7
        return (self.specs["tops"] * efficiency) / model_tops

3Intel OpenVINO 생태계

Intel의 OpenVINO는 CPU, iGPU, VPU(Neural Compute Stick) 등 다양한 Intel 하드웨어에서 통합 추론 API를 제공합니다. x86 아키텍처와의 호환성이 뛰어나 기존 산업용 PC에 쉽게 통합할 수 있습니다.

from openvino.runtime import Core, CompiledModel
import numpy as np
from typing import List, Optional

class OpenVINODeviceSelector:
    """OpenVINO 디바이스 선택 및 벤치마크"""

    def __init__(self):
        self.core = Core()
        self.available_devices = self.core.available_devices

    def get_device_info(self) -> dict:
        """사용 가능한 디바이스 정보"""
        info = {}
        for device in self.available_devices:
            info[device] = {
                "full_name": self.core.get_property(device, "FULL_DEVICE_NAME"),
                "supported_properties": self.core.get_property(
                    device, "SUPPORTED_PROPERTIES"
                )
            }
        return info

    def benchmark_model(
        self,
        model_path: str,
        device: str,
        iterations: int = 100
    ) -> dict:
        """특정 디바이스에서 모델 벤치마크"""
        import time

        # 모델 컴파일
        model = self.core.read_model(model_path)
        compiled = self.core.compile_model(model, device)
        infer_request = compiled.create_infer_request()

        # 입력 준비
        input_tensor = np.random.randn(*model.inputs[0].shape).astype(np.float32)

        # 웜업
        for _ in range(10):
            infer_request.infer({0: input_tensor})

        # 벤치마크
        latencies = []
        for _ in range(iterations):
            start = time.perf_counter()
            infer_request.infer({0: input_tensor})
            latencies.append((time.perf_counter() - start) * 1000)

        return {
            "device": device,
            "mean_latency_ms": np.mean(latencies),
            "p99_latency_ms": np.percentile(latencies, 99),
            "throughput_fps": 1000 / np.mean(latencies)
        }

    def auto_select_device(
        self,
        model_path: str,
        target_latency_ms: float
    ) -> str:
        """지연시간 요구사항 기반 자동 디바이스 선택"""
        results = []
        for device in self.available_devices:
            try:
                benchmark = self.benchmark_model(model_path, device)
                if benchmark["p99_latency_ms"] <= target_latency_ms:
                    results.append((device, benchmark))
            except Exception:
                continue

        # 지연시간 충족하면서 가장 저전력 선택
        priority = ["MYRIAD", "GPU", "CPU"]
        for p in priority:
            for device, _ in results:
                if p in device:
                    return device
        return "CPU"

4Google Coral Edge TPU

Google Coral은 Edge TPU를 통해 초저전력(2W 미만)으로 ML 추론을 가속합니다. TensorFlow Lite 모델에 최적화되어 있으며, 양자화된 INT8 모델만 지원합니다.

from pycoral.adapters import common, classify
from pycoral.utils.edgetpu import make_interpreter, list_edge_tpus
from PIL import Image
import numpy as np
import time

class CoralTPUInference:
    """Google Coral Edge TPU 추론 엔진"""

    def __init__(self, model_path: str, device_index: int = 0):
        # Edge TPU 디바이스 목록
        self.edge_tpus = list_edge_tpus()
        if not self.edge_tpus:
            raise RuntimeError("Edge TPU가 감지되지 않음")

        # 인터프리터 초기화
        # 모델명에 _edgetpu.tflite 포함 필수
        self.interpreter = make_interpreter(
            model_path,
            device=f":0" if device_index == 0 else f":{device_index}"
        )
        self.interpreter.allocate_tensors()

        # 입출력 정보
        self.input_details = self.interpreter.get_input_details()[0]
        self.output_details = self.interpreter.get_output_details()[0]

    def preprocess(self, image: Image.Image) -> np.ndarray:
        """이미지 전처리"""
        size = common.input_size(self.interpreter)
        image = image.resize(size, Image.LANCZOS)
        return np.asarray(image)

    def infer(self, image: Image.Image) -> tuple:
        """추론 실행"""
        # 전처리
        input_data = self.preprocess(image)

        # 추론
        start = time.perf_counter()
        common.set_input(self.interpreter, input_data)
        self.interpreter.invoke()
        latency = (time.perf_counter() - start) * 1000

        # 결과
        output = common.output_tensor(self.interpreter, 0)
        return output, latency

    def get_device_info(self) -> dict:
        """연결된 Edge TPU 정보"""
        return {
            "count": len(self.edge_tpus),
            "devices": [
                {"type": tpu["type"], "path": tpu["path"]}
                for tpu in self.edge_tpus
            ]
        }

Coral TPU는 INT8 양자화 모델만 지원합니다. 모델 변환 시 `edgetpu_compiler`를 사용해 Edge TPU용 오프라인 컴파일이 필요합니다.

5디바이스 비교 분석

각 플랫폼의 특성을 비교하여 애플리케이션 요구사항에 맞는 최적의 선택을 할 수 있습니다.

항목 Jetson Orin Intel NCS2 Coral TPU 산업용 IPC
연산 성능 275 TOPS 4 TOPS 4 TOPS 가변
전력 소비 15-60W ~2W ~2W 50-100W+
프레임워크 TensorRT, ONNX OpenVINO TFLite 다양
FP16 지원 아니오 가변
동적 모델 컴파일 필요
산업 인증 일부 제한적 소비자급 CE/UL
가격대 $200-2000 ~$70 ~$60 $500+

6애플리케이션별 선택 가이드

제조 현장의 다양한 AI 애플리케이션에 따라 최적의 디바이스 선택이 달라집니다.

1

비전 검사 (단일 카메라, <100ms)

권장: Coral TPU 또는 Intel NCS2. 저전력으로 단일 모델 추론에 최적. 열 관리 용이

2

멀티 카메라 검사 (4+ 스트림, 실시간)

권장: Jetson AGX Orin. 다중 디코더와 GPU 병렬 처리로 멀티 스트림 지원

3

예측 정비 (시계열, 저빈도)

권장: 산업용 IPC + OpenVINO. 기존 인프라 활용, 안정성 우선

4

로봇 제어 (고정밀, <10ms)

권장: Jetson Orin NX + TensorRT. 초저지연 추론과 다양한 I/O 지원

7통합 디바이스 선택기

요구사항 기반으로 최적의 엣지 디바이스를 자동으로 추천하는 선택기를 구현합니다.

from dataclasses import dataclass
from enum import Enum
from typing import List, Optional

class ApplicationType(Enum):
    VISION_INSPECTION = "vision_inspection"
    MULTI_CAMERA = "multi_camera"
    PREDICTIVE_MAINTENANCE = "predictive_maintenance"
    ROBOT_CONTROL = "robot_control"
    ANOMALY_DETECTION = "anomaly_detection"

@dataclass
class Requirements:
    application: ApplicationType
    latency_ms: float
    power_budget_w: float
    camera_count: int = 1
    model_size_mb: float = 50
    need_industrial_cert: bool = False
    budget_usd: float = 1000

@dataclass
class DeviceRecommendation:
    device: str
    score: float
    reasons: List[str]
    estimated_fps: float
    estimated_power: float

class EdgeDeviceSelector:
    """요구사항 기반 엣지 디바이스 추천"""

    DEVICES = {
        "jetson_orin_nano": {
            "tops": 40, "power": 15, "price": 500,
            "cameras": 4, "industrial": False
        },
        "jetson_agx_orin": {
            "tops": 275, "power": 60, "price": 2000,
            "cameras": 16, "industrial": True
        },
        "coral_tpu": {
            "tops": 4, "power": 2, "price": 60,
            "cameras": 1, "industrial": False
        },
        "intel_ncs2": {
            "tops": 4, "power": 2, "price": 70,
            "cameras": 1, "industrial": False
        },
        "industrial_ipc_gpu": {
            "tops": 50, "power": 100, "price": 1500,
            "cameras": 8, "industrial": True
        }
    }

    def recommend(self, req: Requirements) -> List[DeviceRecommendation]:
        """요구사항 기반 디바이스 추천"""
        recommendations = []

        for name, spec in self.DEVICES.items():
            score, reasons = self._evaluate(name, spec, req)
            if score > 0:
                est_fps = self._estimate_fps(spec, req)
                recommendations.append(DeviceRecommendation(
                    device=name,
                    score=score,
                    reasons=reasons,
                    estimated_fps=est_fps,
                    estimated_power=spec["power"]
                ))

        return sorted(recommendations, key=lambda x: x.score, reverse=True)

    def _evaluate(self, name: str, spec: dict, req: Requirements) -> tuple:
        """디바이스 적합성 평가"""
        score = 100
        reasons = []

        # 필수 조건 확인
        if req.need_industrial_cert and not spec["industrial"]:
            return 0, ["산업 인증 미충족"]

        if spec["cameras"] < req.camera_count:
            return 0, ["카메라 수 미충족"]

        if spec["price"] > req.budget_usd:
            score -= 30
            reasons.append("예산 초과")

        if spec["power"] > req.power_budget_w:
            score -= 20
            reasons.append("전력 예산 초과")
        else:
            reasons.append("전력 요구사항 충족")

        # 성능 여유도
        required_tops = req.model_size_mb / 10  # 대략적 추정
        if spec["tops"] >= required_tops * 2:
            score += 10
            reasons.append("충분한 성능 여유")

        return max(0, score), reasons

    def _estimate_fps(self, spec: dict, req: Requirements) -> float:
        """예상 FPS 계산"""
        # 간단한 추정: TOPS / 모델 크기 기반
        ops_per_frame = req.model_size_mb * 1e6  # 대략적 연산량
        return (spec["tops"] * 1e12 * 0.7) / ops_per_frame

8환경 요구사항

제조 현장의 가혹한 환경에서 안정적으로 동작하기 위해 디바이스의 환경 사양을 반드시 확인해야 합니다.

온도 범위

산업용: -40~85°C

상용: 0~50°C

열 관리 필수 방열판

진동/충격

IEC 60068-2-6

5G/10-500Hz

SSD 권장 고정 장착

전원

DC 9-36V 광범위 입력

UPS 연동 권장

서지 보호 역극성 보호

EMC/EMI

CE/FCC Class B

산업용 Class A

차폐 케이스 페라이트 코어