Immich 机器学习硬件加速实战:GPU/NPU 加速智能搜索与人脸识别全指南
Immich 的智能搜索(Smart Search)、人脸识别和 OCR 等任务默认运行在 CPU 上,耗时较长且占用大量算力。官方通过 immich-machine-learning 容器的后端变体(CUDA、ROCm、OpenVINO、ARM NN、RKNN)让这些推理任务下沉到 GPU 或 NPU,显著降低 CPU 负载。读完本文,你将能够:为自己的硬件选型并配置合适的加速后端、正确修改 docker-compose.yml、在多 GPU 环境下分配设备,并理解 ML 服务选择推理后端的源码级原理。
功能概览与适用边界
该功能允许使用 GPU 加速机器学习任务(智能搜索、人脸识别等),同时降低 CPU 负载。由于仍属实验性功能,可能无法在所有系统上正常工作,配置前请先阅读下述限制。
一个重要的事实是:启用硬件加速后,无需重跑任何已有的机器学习任务。加速设备会用于启用之后运行的所有新任务,已完成的向量与人脸数据保持有效。
限制条件(摘自官方文档)
- 文中指令与配置针对 Docker Compose;其他容器引擎可能需要不同的配置方式;
- 仅支持 Linux 与 Windows(通过 WSL2)服务器;
- ARM NN 仅支持配备 Mali GPU 的设备,其他 Arm 设备不支持;
- 某些模型可能与特定后端不兼容,其中 CUDA 的兼容性最可靠;
- ARM NN 受模型兼容性问题影响,无法加速搜索(Search)延迟,但智能搜索的批处理任务可以使用 ARM NN。
支持的推理后端
| 后端 | 目标硬件 | 底层运行时 |
|---|---|---|
| ARM NN | 搭载 Mali GPU 的 Arm 设备 | ARM NN / libmali |
| CUDA | 计算能力(compute capability)≥ 5.2 的 NVIDIA GPU | ONNX Runtime CUDAExecutionProvider |
| ROCm | AMD GPU(MIGraphX) | ONNX Runtime MIGraphXExecutionProvider |
| OpenVINO | Intel GPU(Iris Xe、Arc 等) | ONNX Runtime OpenVINOExecutionProvider |
| RKNN | Rockchip SoC(RK3566/3568/3576/3588) | RKNN NPU 运行时 |
从源码看,ONNX Runtime 路径的候选执行提供方在 constants.py 中按优先级顺序定义:
SUPPORTED_PROVIDERS = [
"CUDAExecutionProvider",
"MIGraphXExecutionProvider",
"OpenVINOExecutionProvider",
"CoreMLExecutionProvider",
"CPUExecutionProvider",
]
服务启动时会比对 ort.get_available_providers() 与该列表,只保留当前镜像中实际可用的提供方(见 ort.py)。也就是说,cpu 镜像只有 CPUExecutionProvider,而 -cuda 镜像才会出现 CUDAExecutionProvider——这解释了为什么启用加速必须更换镜像 tag。
各后端的前置条件
ARM NN(Mali GPU)
- 确保已安装正确的 Linux 内核驱动(通常设备厂商的 Linux 镜像已预装);
- 宿主机上必须存在
/dev/mali0,可用ls /dev确认; - 必须有闭源的
libmali.so固件(可能还需要额外的固件文件),获取方式取决于设备与厂商; - hwaccel.ml.yml 中假定
libmali.so位于/usr/lib/libmali.so、额外固件位于/lib/firmware/mali_csffw.bin,路径不同请相应修改; - 可选:在
.env中配置 ARM NN 相关变量,特别是MACHINE_LEARNING_ANN_FP16_TURBO——它以非常轻微的精度损失换取显著的性能提升(默认值False,见 config.py)。
CUDA(NVIDIA)
- GPU 计算能力 ≥ 5.2;
- 服务器必须安装官方 NVIDIA 驱动,且驱动版本 ≥ 545(需支持 CUDA 12.3);
- Linux(WSL2 除外)还需安装 NVIDIA Container Toolkit。
ROCm(AMD)
- Linux 下需安装 AMDGPU 驱动模块;若启用 Secure Boot,需将 DKMS 签名密钥注册进 UEFI BIOS;
- GPU 需被 ROCm 支持。若官方未支持,可尝试环境变量
HSA_OVERRIDE_GFX_VERSION=<受支持的版本,如 10.3.0>;若仍不行,可能还需设置HSA_USE_SVM=0; - ROCm 镜像体积较大,至少需要 35 GiB 空闲磁盘空间。后续通过 Docker 拉取更新一般只有几百 MB,其余层会被缓存;
- 该后端较新,可能出现问题。例如推理结束后(即使 ML 服务空闲)GPU 功耗可能高于常态,需空闲约 5 分钟后恢复正常——该时间由
MACHINE_LEARNING_MODEL_TTL(默认 300 秒)控制,对应源码中的 model_ttl 设置; - MIGraphX 会在运行时编译模型,因此前几次推理会比较慢。源码中可以看到针对 MIGraphX 的特殊处理:首次对某一输入签名推理时会加锁编译并缓存,且自动创建模型缓存目录 migraphx、ort.py#L136-L144。
OpenVINO(Intel)
- 集显比独显更容易出问题,尤其是老处理器或内存较小的服务器;
- 确保服务器内核版本足够新,能够使用设备做硬件加速;
- 相比纯 CPU 处理,OpenVINO 会带来更高的内存占用。
从源码看,OpenVINO 提供方会枚举可用设备,优先选择 GPU.<device_id>,找不到 GPU 时回退到 CPU,并使用 MACHINE_LEARNING_OPENVINO_PRECISION(默认 FP32)作为推理精度(ort.py#L145-L159)。
OpenVINO-WSL(Windows)
- 确认容器能访问
/dev/dri,可执行docker exec -t immich_machine_learning ls -la /dev/dri验证; - 若不能,在 WSL 宿主机上运行
getent group render与getent group video查询组 ID,并将这些组加入 hwaccel.ml.yml 的openvino-wsl段:
openvino-wsl:
devices:
- /dev/dri:/dev/dri
- /dev/dxg:/dev/dxg
volumes:
- /dev/bus/usb:/dev/bus/usb
- /usr/lib/wsl:/usr/lib/wsl
group_add:
- 44 # 替换为 getent group video 查到的组 ID
- 992 # 替换为 getent group render 查到的组 ID
仓库中 hwaccel.ml.yml 的 openvino-wsl 段即该配置的基础,group_add 需按上一步查询结果自行补充。
RKNN(Rockchip NPU)
- 必须是受支持的 Rockchip SoC:目前仅 RK3566、RK3568、RK3576、RK3588(该清单与源码中 RKNN_SUPPORTED_SOCS 完全一致);
- 确保已安装正确的 Linux 内核驱动(厂商镜像通常预装);
- 宿主机需有 RKNPU 驱动 V0.9.8 或更高版本,可用
cat /sys/kernel/debug/rknpu/version确认; - 可选:在
.env中配置 RKNN 相关变量。特别是将MACHINE_LEARNING_RKNN_THREADS设为 2 或 3,相比默认值 1 可大幅提升 RK3576/RK3588 的性能,代价是每个模型占用的内存按倍数增加(默认值 1,见 config.py)。
RKNN 推理路径独立于 ONNX Runtime:RknnSession 会按 rknn_threads 创建线程池执行 rknn_lite.inference,并在可用时按 SoC 名称缓存模型(rknpu/<soc_name> 前缀)。
配置步骤(Docker Compose 方式)
- 若尚未拥有 hwaccel.ml.yml,请下载最新版本(仓库中随发行版分发该文件),并确保它与
docker-compose.yml位于同一目录; - 在
docker-compose.yml的immich-machine-learning服务中,将image标签末尾加上-[armnn, cuda, rocm, openvino, rknn]之一; - 仍在
immich-machine-learning服务下,取消注释extends段,并把cpu改为对应后端(WSL2 下按需使用-wsl变体); - 用更新后的配置重新部署
immich-machine-learning容器。
仓库中的 docker-compose.yml 已预置了注释好的模板:
immich-machine-learning:
container_name: immich_machine_learning
# For hardware acceleration, add one of -[armnn, cuda, rocm, openvino, rknn] to the image tag.
# Example tag: ${IMMICH_VERSION:-release}-cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
# extends: # uncomment this section for hardware acceleration
# file: hwaccel.ml.yml
# service: cpu # set to one of [armnn, cuda, rocm, openvino, openvino-wsl, rknn]
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
extends 引用的 hwaccel.ml.yml 为每个后端定义了最小设备映射,例如:
services:
cuda:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities:
- gpu
rocm:
group_add:
- video
devices:
- /dev/dri:/dev/dri
- /dev/kfd:/dev/kfd
rknn:
security_opt:
- systempaths=unconfined
- apparmor=unconfined
devices:
- /dev/dri:/dev/dri
armnn:
devices:
- /dev/mali0:/dev/mali0
volumes:
- /lib/firmware/mali_csffw.bin:/lib/firmware/mali_csffw.bin:ro
- /usr/lib/libmali.so:/usr/lib/libmali.so:ro
注意 RKNN 段使用了 security_opt: unconfined——因为容器需要直接访问 /dev/dri 下的 NPU 节点并调用厂商驱动,默认安全策略会阻止。
单一 Compose 文件(Unraid / Portainer 等)
部分平台(包括 Unraid 和 Portainer)不支持多个 Compose 文件。替代做法是把 hwaccel.ml.yml 中对应后端的内容内联进 immich-machine-learning 服务。例如 cuda 段是:
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities:
- gpu
合并后的完整服务(不再使用 extends):
immich-machine-learning:
container_name: immich_machine_learning
# 注意末尾的 -cuda
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}-cuda
# 注意此处没有 extends 段
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities:
- gpu
volumes:
- model-cache:/cache
env_file:
- .env
restart: always
完成后重新部署 immich-machine-learning 容器即可。
多 GPU 配置
要使用多块 NVIDIA 或 Intel GPU,将 MACHINE_LEARNING_DEVICE_IDS 设为逗号分隔的设备 ID 列表,并把 MACHINE_LEARNING_WORKERS 设为与设备数一致。可用 nvidia-smi -L 或 glxinfo -B 查看当前设备及 ID:
MACHINE_LEARNING_DEVICE_IDS=0,1
MACHINE_LEARNING_WORKERS=2
此时 ML 服务会启动两个 worker:一个把模型分配到设备 0,另一个分配到设备 1,不同请求由其中一个 worker 处理。
从源码看,设备分配发生在 gunicorn_conf.py:gunicorn 按 worker 序号对设备列表取模(round-robin),把 MACHINE_LEARNING_DEVICE_ID 注入每个 worker 的环境;随后 CUDA/MIGraphX/OpenVINO 的提供方选项都读取该 device_id(ort.py#L135、ort.py#L141)。这解释了 environment-variables.md 中“每个 worker 轮询分配一块设备、且必须 MACHINE_LEARNING_WORKERS > 1”的说明。
这一机制也可以用来固定使用某块特定设备:例如 MACHINE_LEARNING_DEVICE_IDS=1 会确保始终使用设备 1 而非设备 0。
需要注意:
- 要提高整体利用率、更高效地在多 GPU 间分布负载,应同步提高任务并发度(job concurrency);
- 每块 GPU 都必须能独立加载全部模型——不能把一个模型拆分到多块 VRAM 不足的 GPU 上,也不能把某个特定模型指定到某块 GPU。
确认设备被识别与使用
可以通过多种方式验证加速设备已生效:
- 观察利用率:NVIDIA 与 Intel 可用
nvtop,Intel 可用intel_gpu_top,AMD 可用radeontop; - 查看容器日志:当智能搜索或人脸检测任务开始,或在 Immich 中进行文字搜索时,日志中应出现二选一:
Available ORT providers日志,且包含对应提供方(如 CUDA 的CUDAExecutionProvider)——该日志正来自 ort.py#L115 的 provider 探测;- 对 ARM NN,则是
Loaded ANN model且无报错的日志条目。
相关环境变量速查
结合 environment-variables.md 与 config.py 中的默认值,与硬件加速最相关的变量如下:
| 变量 | 说明 | 默认值 |
|---|---|---|
MACHINE_LEARNING_WORKERS |
worker 进程数(多 GPU 时等于设备数) | 1 |
MACHINE_LEARNING_DEVICE_IDS |
多 GPU 环境的设备 ID 列表 | 0 |
MACHINE_LEARNING_ANN |
支持时启用 ARM NN 加速 | True |
MACHINE_LEARNING_ANN_FP16_TURBO |
ARM NN 以 FP16 执行:提速、轻微降精度 | False |
MACHINE_LEARNING_ANN_TUNING_LEVEL |
ARM NN GPU 调优级别(1: rapid, 2: normal, 3: exhaustive) | 2 |
MACHINE_LEARNING_RKNN |
支持时启用 RKNN 加速 | True |
MACHINE_LEARNING_RKNN_THREADS |
RKNN 推理时启动的运行时线程数 | 1 |
MACHINE_LEARNING_OPENVINO_PRECISION |
OpenVINO 精度(FP16/FP32) |
FP32 |
MACHINE_LEARNING_MODEL_TTL |
模型空闲卸载时间(秒),影响 ROCm 功耗回落 | 300 |
MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION |
人脸模型单次处理的最大人脸数 | None(OpenVINO 为 1) |
MACHINE_LEARNING_MAX_BATCH_SIZE__OCR |
OCR 模型单次处理的最大框数 | 6 |
补充调优细节:
- 默认 CPU 线程策略在源码中有体现——
MACHINE_LEARNING_MODEL_INTER_OP_THREADS/MACHINE_LEARNING_MODEL_INTRA_OP_THREADS为 0 时,仅在纯 CPU 提供方下分别回退为 1/2,因为“这些默认值对 CPU 合适但会拖累 GPU”(ort.py#L184-L206); - ROCm 下 worker 超时默认放宽为 900 秒(其余为 300 秒),见 default_worker_timeout;
- 首次搜索较慢时,可用
MACHINE_LEARNING_PRELOAD__*系列变量预加载视觉/人脸/OCR 模型,避免备份触发首次加载时阻塞其他请求(main.py#L78-L119 实现了启动时预加载)。
实用技巧(官方 Tips 汇总)
- 若某模型运行时报错,换一个模型试试,判断问题是否为模型特定;
- 可适当提高并发度以提升利用率,但注意这会增加 VRAM 消耗;
- 模型越大,从硬件加速中获益越多(前提是 VRAM 足够);
- RKNPU 与 ARM NN 的对比:
- 模型支持更广(包括搜索任务,而 ARM NN 不加速搜索);
- 发热更低;
- 精度极轻微降低(RKNPU 恒用 FP16,ARM NN 默认用更高精度的 FP32,除非启用
MACHINE_LEARNING_ANN_FP16_TURBO); - 速度表现(以 RK3588 实测为参考):
MACHINE_LEARNING_RKNN_THREADS为默认 1 时,RKNPU 的 ML 任务吞吐通常明显低于 ARM NN,但延迟相近(如搜索场景);- 设为 3 时,RKNPU 略快于 FP32 的 ARM NN,但略慢于开启
MACHINE_LEARNING_ANN_FP16_TURBO的 ARM NN; - 当 GPU 同时被其他任务(如转码)占用时,RKNPU 使用本来空闲的 NPU,相比争抢 GPU 的 ARM NN 有显著优势;
- 内存占用:线程数为 1 时更低;大于 1 时明显更高(但要发挥 NPU 全部性能、追平 ARM NN 的速度必须大于 1)。
小结
Immich 的 ML 硬件加速本质上是通过“镜像变体 + Compose extends”切换 ONNX Runtime 执行提供方或 NPU 独立运行时(RKNN/ARM NN),实现与 CPU 完全兼容的加速路径:已完成的向量与人脸数据无需重算,新任务自动落到加速设备。配置时的核心决策链是——先确认硬件与驱动满足对应后端的前置条件,再选择镜像 tag、内联或 extends 后端配置、按需设置 MACHINE_LEARNING_DEVICE_IDS/WORKERS 与精度/线程类变量,最后用设备利用率和容器日志(Available ORT providers / Loaded ANN model)双重验证。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00