From ab208155845cfbdaabb39085392b09fd75e7a299 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Sun, 30 Aug 2026 11:15:49 -0600 Subject: [PATCH] Fix NPU turbo key and priviledges set (#24138) --- .../etc/s6-overlay/s6-rc.d/init-devices/run | 1 + docs/docs/configuration/non_root.md | 2 +- docs/docs/configuration/object_detectors.md | 2 ++ frigate/detectors/detection_runners.py | 25 +++++++++++++------ 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/init-devices/run b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/init-devices/run index b1591a1e1f..72bbc0434c 100755 --- a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/init-devices/run +++ b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/init-devices/run @@ -24,6 +24,7 @@ shopt -s nullglob device_globs=( "/dev/dri/*" + "/dev/accel/*" "/dev/apex_*" "/dev/hailo*" "/dev/video*" diff --git a/docs/docs/configuration/non_root.md b/docs/docs/configuration/non_root.md index af47cfef50..b62b856291 100644 --- a/docs/docs/configuration/non_root.md +++ b/docs/docs/configuration/non_root.md @@ -124,7 +124,7 @@ The escape hatch never changes ownership, and it clears the record of the last s Frigate grants the runtime user access to your devices at startup. Pass your hardware with `--device` (or `devices:` in compose) and detection and hardware acceleration work with no group or udev setup on the host. -The grant covers the common accelerator and camera nodes: GPU render nodes, Coral, Hailo, Rockchip, Jetson, `/dev/video*`, and the USB bus. For hardware it misses, add your own paths with `DEVICE_ACL_PATHS`, a comma separated list of globs: +The grant covers the common accelerator and camera nodes: GPU render nodes, Intel/AMD NPUs (`/dev/accel`), Coral, Hailo, Rockchip, Jetson, `/dev/video*`, and the USB bus. For hardware it misses, add your own paths with `DEVICE_ACL_PATHS`, a comma separated list of globs: ```yaml environment: diff --git a/docs/docs/configuration/object_detectors.md b/docs/docs/configuration/object_detectors.md index 9a8b143610..92ff0b2317 100644 --- a/docs/docs/configuration/object_detectors.md +++ b/docs/docs/configuration/object_detectors.md @@ -338,6 +338,8 @@ models: ### Intel NPU host requirements {#intel-npu-requirements} +The NPU device must be passed into the container by adding `/dev/accel:/dev/accel` to the `devices` section of your compose file. Frigate grants the runtime user access to the device automatically; see [hardware device access](/configuration/non_root#hardware-device-access) if you manage device permissions yourself. + The NPU firmware is loaded by the host kernel and is not part of the Frigate image. Everything else the NPU needs is bundled in the container, so host NPU libraries should never be mounted in. Frigate bundles a specific version of Intel's [linux-npu-driver](https://github.com/intel/linux-npu-driver/releases), and the host firmware must come from that release or a newer one. Firmware older than the bundled driver may fail with `MAPPED_INFERENCE_VERSION is NOT compatible with the ELF`, where `Expected` is the version the firmware supports and `received` is the version the bundled compiler produced. Distributions often package older firmware than the driver Frigate ships, so check the build date on the host with `sudo dmesg | grep -i vpu` and update it there if needed. diff --git a/frigate/detectors/detection_runners.py b/frigate/detectors/detection_runners.py index 0ad6cfa255..6d1486745e 100644 --- a/frigate/detectors/detection_runners.py +++ b/frigate/detectors/detection_runners.py @@ -320,17 +320,28 @@ class OpenVINOModelRunner(BaseModelRunner): except Exception as e: logger.debug(f"GPU_QUEUE_THROTTLE not supported: {e}") + # Some keys must be passed as compile-time config so that it can be caught + compile_config = {} + if device == "NPU" and OpenVINOModelRunner.is_detection_model(model_type): - try: - self.ov_core.set_property(device, {"NPU_TURBO": "YES"}) - except Exception as e: - logger.debug(f"NPU_TURBO not supported by driver: {e}") + compile_config["NPU_TURBO"] = "YES" # Compile model under the shared lock with _OPENVINO_LOCK: - self.compiled_model = self.ov_core.compile_model( - model=model_path, device_name=device - ) + try: + self.compiled_model = self.ov_core.compile_model( + model=model_path, device_name=device, config=compile_config + ) + except RuntimeError as e: + if not compile_config: + raise + + logger.debug( + f"Failed to compile with {compile_config}, retrying without: {e}" + ) + self.compiled_model = self.ov_core.compile_model( + model=model_path, device_name=device + ) # Create reusable inference request self.infer_request = self.compiled_model.create_infer_request()