# Edge AI Inferencing Patterns **Last updated:** 2026-02 **Status:** GA **Category:** Hybrid Cloud & Edge AI --- ## Introduksjon Edge AI-inferens handler om a kjore maskinlaeringsmodeller naermest mulig der data oppstar — pa enheter, gateways, lokale servere eller Azure Local-klynger. For norsk offentlig sektor er dette relevant i scenarioer som sanntids videoanalyse, dokumentbehandling i felt, naturspraakbehandling offline, og autonome systemer i omrader med begrenset nettverkstilkobling. Microsoft tilbyr et bredt spekter av verktoy for edge-inferens: ONNX Runtime som universell inferensmotor, Azure IoT Edge for container-baserte modeller, Azure Stack Edge for hardware-akselerert inferens, og KAITO for LLM-deployment pa Kubernetes. Valget av moenster avhenger av modellstorrelse, latenskrav, tilgjengelig hardware og tilkoblingsstatus. Denne referansen dekker de viktigste moensterne for modelloptimalisering, akselerasjon, caching og batching/streaming — alle med fokus pa Microsoft Azure-okosystemet og relevans for offentlig sektor. --- ## Model Quantization og Compression ### Hva er kvantisering? Kvantisering reduserer presisjonen til modellvekter fra hoyere til lavere bit-representasjoner, noe som reduserer modellstorrelse og oker inferenshastighet med minimalt noyaktighetstap. | Presisjon | Bits | Storrelse (7B modell) | Hastighet | Noyaktighet | |-----------|------|----------------------|-----------|-------------| | FP32 | 32 | ~28 GB | Baseline | 100% | | FP16 | 16 | ~14 GB | 2x | ~99.9% | | BF16 | 16 | ~14 GB | 2x | ~99.9% | | INT8 | 8 | ~7 GB | 3-4x | ~99% | | INT4 | 4 | ~3.5 GB | 5-8x | ~97% | ### Kvantiseringsmetoder i Azure-okosystemet | Metode | Verktoy | Best for | Presisjon | |--------|---------|----------|-----------| | Post-Training Quantization (PTQ) | ONNX Runtime, Olive | Rask konvertering | INT8/INT4 | | Quantization-Aware Training (QAT) | PyTorch + Azure ML | Hoyest noyaktighet | INT8 | | GPTQ | HuggingFace + KAITO | LLM-kvantisering | INT4 | | AWQ | HuggingFace + KAITO | LLM-kvantisering | INT4 | | Dynamic Quantization | ONNX Runtime | CPU-inferens | INT8 | ### ONNX Runtime-kvantisering ```python # Kvantiser ONNX-modell til INT8 from onnxruntime.quantization import quantize_dynamic, QuantType quantize_dynamic( model_input="model_fp32.onnx", model_output="model_int8.onnx", weight_type=QuantType.QInt8, optimize_model=True ) ``` ### Olive — Microsofts modelloptimalisering Olive er Microsofts verktoy for helhetlig modelloptimalisering: ```python # olive_config.json { "input_model": { "type": "OnnxModel", "model_path": "model.onnx" }, "systems": { "local_system": { "type": "LocalSystem", "accelerators": [{"device": "npu"}] } }, "passes": { "quantization": { "type": "OnnxQuantization", "config": { "quant_mode": "static", "quant_format": "QDQ", "calibration_data_reader": "CalibrationDataReader" } }, "perf_tuning": { "type": "OrtPerfTuning", "config": { "data_dir": "./calibration_data" } } }, "engine": { "search_strategy": { "execution_order": "joint", "search_algorithm": "exhaustive" }, "output_dir": "./optimized" } } ``` ### Modellkomprimering | Teknikk | Beskrivelse | Storrelsereduksjon | Noyaktighetstap | |---------|-------------|-------------------|-----------------| | Pruning | Fjerner uvesentlige vekter | 30-70% | 1-3% | | Knowledge Distillation | Laerer liten modell fra stor | 50-90% | 2-5% | | Weight Sharing | Deler vekter mellom lag | 20-40% | <1% | | Low-Rank Factorization | Dekomponerer vektmatriser | 30-50% | 1-2% | --- ## Real-time Inference Acceleration ### ONNX Runtime Execution Providers ONNX Runtime stotter flere hardware-akseleratorer gjennom Execution Providers (EP): | Execution Provider | Hardware | Best for | Latens | |--------------------|----------|----------|--------| | CPU EP | x86/ARM CPU | Universell | Basis | | CUDA EP | NVIDIA GPU | GPU-inferens | 5-50x raskere | | TensorRT EP | NVIDIA GPU | Optimalisert GPU | 10-100x raskere | | OpenVINO EP | Intel CPU/GPU/VPU | Intel-optimalisert | 3-20x raskere | | DirectML EP | Windows GPU/NPU | Windows-enheter | 5-30x raskere | | QNN EP | Qualcomm NPU | Snapdragon-enheter | 10-50x raskere | ### GPU-akselerert inferens med ONNX Runtime ```python import onnxruntime as ort # Konfigurasjon for NVIDIA GPU (TensorRT) session_options = ort.SessionOptions() session_options.graph_optimization_level = \ ort.GraphOptimizationLevel.ORT_ENABLE_ALL providers = [ ('TensorrtExecutionProvider', { 'trt_max_workspace_size': 2147483648, # 2 GB 'trt_fp16_enable': True, 'trt_engine_cache_enable': True, 'trt_engine_cache_path': './trt_cache' }), ('CUDAExecutionProvider', { 'device_id': 0, 'arena_extend_strategy': 'kSameAsRequested', 'gpu_mem_limit': 4 * 1024 * 1024 * 1024, # 4 GB 'cudnn_conv_algo_search': 'DEFAULT' }), 'CPUExecutionProvider' ] session = ort.InferenceSession( "model_fp16.onnx", sess_options=session_options, providers=providers ) # Inferens result = session.run(None, {"input": input_data}) ``` ### OpenVINO Model Server (OVMS) pa Edge For Azure Arc/Azure Local-miljoer der Intel-hardware brukes: ```yaml # ovms-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: ovms-inference spec: replicas: 2 template: spec: containers: - name: ovms image: openvino/model_server:latest ports: - containerPort: 9000 # gRPC - containerPort: 8000 # REST volumeMounts: - name: model-store mountPath: /models env: - name: MODELS_CONFIG value: "/models/config.json" resources: limits: cpu: "4" memory: "8Gi" volumes: - name: model-store persistentVolumeClaim: claimName: model-pvc ``` ### vLLM for LLM-inferens KAITO bruker vLLM som standard inferensmotor for LLM-er: | Funksjon | Beskrivelse | Fordel | |----------|-------------|--------| | PagedAttention | Effektiv KV-cache-haandtering | 2-4x gjennomstromning | | Continuous batching | Dynamisk batching av foresporsler | Redusert latens | | Tensor parallelism | Fordel modell over GPUer | Storre modeller | | Quantization support | AWQ, GPTQ, SqueezeLLM | Lavere minnebruk | | OpenAI-compatible API | Standard API-format | Enkel integrasjon | --- ## Caching Patterns for Edge ### Modellcaching-strategier | Strategi | Implementasjon | Bruksomrade | |----------|---------------|-------------| | Model preloading | Last modell i minne ved oppstart | Sanntids inferens | | TensorRT engine cache | Cach kompilerte TRT-motorer | GPU-inferens | | ONNX session cache | Gjenbruk ORT-sesjoner | Repetitive inferenser | | Result caching | Redis/memcached for resultater | Identiske inputs | | Embedding cache | Cach vektorrepresentasjoner | RAG pa edge | ### Resultatchaching med Redis pa Edge ```yaml # redis-cache-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: inference-cache spec: template: spec: containers: - name: redis image: redis:7-alpine ports: - containerPort: 6379 resources: limits: memory: "2Gi" args: - "--maxmemory" - "1.5gb" - "--maxmemory-policy" - "allkeys-lru" ``` ```python # Inferens med caching import redis import hashlib import json cache = redis.Redis(host='inference-cache', port=6379) def cached_inference(model_session, input_data, ttl=3600): # Generer cache-nokkel fra input cache_key = hashlib.sha256( json.dumps(input_data, sort_keys=True).encode() ).hexdigest() # Sjekk cache cached = cache.get(cache_key) if cached: return json.loads(cached) # Kjor inferens result = model_session.run(None, input_data) # Lagre i cache cache.setex(cache_key, ttl, json.dumps(result.tolist())) return result ``` ### KV-cache for LLM-er For LLM-inferens pa edge er KV-cache (key-value cache) kritisk: | Teknikk | Beskrivelse | Minnebesparelse | |---------|-------------|-----------------| | Standard KV-cache | Full cache for alle tokens | Baseline | | Sliding window | Begrens cache til siste N tokens | 50-80% | | Grouped-query attention | Faerre KV-hoder | 4-8x | | PagedAttention (vLLM) | Sidert minnehaandtering | Dynamisk | --- ## Batching vs. Streaming Inference ### Sammenligning | Egenskap | Batch Inference | Streaming Inference | |----------|----------------|---------------------| | Latens | Hoyere (venter pa batch) | Lavere (umiddelbar) | | Gjennomstromning | Hoyere (GPU-utnyttelse) | Lavere (per request) | | GPU-utnyttelse | Optimal (fyller batch) | Variabel | | Bruksomrade | Dokumentanalyse, batch-scoring | Chat, real-time | | Skalering | Horisontal (flere workers) | Vertikal (GPU-kapasitet) | ### Beslutningstre ``` Trenger du sanntidssvar (<100ms)? ├── Ja → Streaming inference │ ├── Enkelt request → Single request pipeline │ └── Flere samtidige → Continuous batching (vLLM) └── Nei → Batch inference ├── <1000 elementer → Micro-batch pa GPU └── >1000 elementer → Azure ML Batch Endpoints ``` ### Batch Inference pa Edge ```python import numpy as np from collections import deque import threading import time class EdgeBatchInferencer: def __init__(self, session, batch_size=8, max_wait_ms=50): self.session = session self.batch_size = batch_size self.max_wait = max_wait_ms / 1000 self.queue = deque() self.lock = threading.Lock() def infer(self, input_data): """Legg til i koe og vent pa batch-resultat.""" event = threading.Event() result_container = {} with self.lock: self.queue.append((input_data, event, result_container)) # Trigger batch hvis full if len(self.queue) >= self.batch_size: self._process_batch() # Vent pa resultat (med timeout) event.wait(timeout=self.max_wait * 2) return result_container.get('result') def _process_batch(self): """Prosesser akkumulerte inputs som en batch.""" with self.lock: items = [] while self.queue and len(items) < self.batch_size: items.append(self.queue.popleft()) if not items: return # Kombiner inputs til batch batch_input = np.stack([item[0] for item in items]) # Kjor batch-inferens batch_results = self.session.run( None, {"input": batch_input} ) # Distribuer resultater for i, (_, event, container) in enumerate(items): container['result'] = batch_results[0][i] event.set() ``` ### Streaming Inference for LLM pa Edge ```python # Streaming med vLLM-kompatibelt API (KAITO) import requests import json def stream_inference(prompt, service_ip, max_tokens=500): """Stream tokens fra lokal LLM pa edge.""" response = requests.post( f"http://{service_ip}/v1/completions", json={ "model": "phi-4-mini-instruct", "prompt": prompt, "max_tokens": max_tokens, "stream": True }, stream=True ) for line in response.iter_lines(): if line: data = line.decode('utf-8') if data.startswith('data: '): chunk = json.loads(data[6:]) if chunk.get('choices'): token = chunk['choices'][0].get('text', '') yield token ``` --- ## IoT Edge ML Inference Pattern ### Azure IoT Edge med dynamisk modellasting ``` ┌─────────────────────────────────────────┐ │ Azure Cloud │ │ ┌──────────┐ ┌──────────────────┐ │ │ │ Blob │ │ IoT Hub │ │ │ │ Storage │ │ (Device Twins) │ │ │ │ (Models) │ │ │ │ │ └────┬─────┘ └────────┬─────────┘ │ └───────┼───────────────────┼─────────────┘ │ │ │ ┌───────────────▼──────────┐ │ │ IoT Edge Runtime │ │ │ ┌─────────────────────┐ │ └───┼─►│ Model Loader Module │ │ │ └──────────┬──────────┘ │ │ ┌──────────▼──────────┐ │ │ │ Inference Module │ │ │ │ (ONNX/LiteRT) │ │ │ └──────────┬──────────┘ │ │ ┌──────────▼──────────┐ │ │ │ Local Storage │ │ │ │ (Model Cache) │ │ │ └─────────────────────┘ │ └──────────────────────────┘ ``` ### Device Twin-basert modellstyring ```python # Motta modelloppdatering via IoT Edge Device Twin from azure.iot.device import IoTHubModuleClient async def twin_update_handler(patch): if 'model_version' in patch: model_url = patch['model_url'] model_version = patch['model_version'] checksum = patch['model_checksum'] # Last ned ny modell await download_model(model_url, checksum) # Hot-swap modell uten nedetid await reload_model(model_version) # Rapporter tilbake reported = { "active_model_version": model_version, "model_loaded_at": datetime.utcnow().isoformat() } client.patch_twin_reported_properties(reported) ``` --- ## Ytelsesreferanser ### Typiske inferenstider pa Microsoft edge-hardware | Hardware | Modell | Oppgave | Latens (ms) | |----------|--------|---------|-------------| | Azure Stack Edge Pro GPU (T4) | YOLOv8 | Objektdeteksjon | 8-15 | | Azure Stack Edge Pro GPU (T4) | ResNet-50 | Bildeklassifisering | 3-5 | | Azure Local (A2) | Phi-3-mini-4k | Tekst (128 tokens) | 200-400 | | Azure Local (L4) | Phi-4-mini | Tekst (128 tokens) | 80-150 | | Azure Local (L40S) | Mistral-7B | Tekst (128 tokens) | 50-100 | | Intel CPU (Xeon) + OpenVINO | BERT-base | NER | 5-10 | | CPU (ONNX Runtime) | DistilBERT | Sentiment | 3-8 | --- ## For Cosmo - **ONNX Runtime er universalmotoren for edge-inferens** — stotter CPU, GPU, NPU via Execution Providers, med TensorRT for NVIDIA og OpenVINO for Intel som de viktigste akseleratorene. - **Kvantisering (INT8/INT4) er den enkleste og mest effektive optimaliseringen** — reduserer modellstorrelse 2-8x med minimalt noyaktighetstap, spesielt viktig for edge-enheter med begrenset minne. - **Velg batching for gjennomstromning, streaming for latens** — continuous batching (vLLM/KAITO) gir det beste av begge for LLM-inferens pa edge Kubernetes-klynger. - **Caching pa flere nivaer er essensielt for edge-ytelse** — TensorRT engine cache, resultat-cache (Redis), og KV-cache for LLM-er reduserer bade latens og GPU-belastning. - **IoT Edge med Device Twins gir skalerbar modellstyring** for distribuerte edge-enheter — modellversjonering, inkrementell oppdatering og hot-swap uten nedetid.