最近在做Amlogic NPU,想把流程记清楚。官方有开源仓库,但对照README自己装一遍,还是会踩到不少坑——尤其是国内网络、Git LFS、以及S905X5平台ID这件事。
这篇就按我自己实际操作的顺序写,走通这条链路:
yolov8n.pt → yolov8n.onnx → yolov8n_s905x5_w8a8.adla
1. amlnn-toolkit是干什么的
amlnn-toolkit是 Amlogic开源的一套转换工具,负责:
- 导入
.onnx/.tflite等模型 - 量化(本文用
w8a8) - 按目标芯片编译
- 导出
.adla
可以简单理解为:
| 格式 | 含义 |
|---|---|
.pt | PyTorch 权重 |
.onnx | 中间交换格式 |
.adla | 给指定 Amlogic NPU 用的可部署模型 |
常见两种用法:
- x86_64 Linux PC:装
amlnn_toolkit,在主机上转换模型(本文) - Amlogic Debian 板端:装 edge toolkit,在板子上跑
相关仓库:
- Amlogic-NN/amlnn-toolkit
- Amlogic-NN/amlnn-model-playground
2. 安装 Miniconda / Miniforge
工具依赖PyTorch、ONNX、TensorFlow一堆包,建议独立Conda 环境,别污染系统 Python。我这边实测机器是x86_64 Linux。如果本机还没有Conda,先装Miniforge(或 Miniconda 也行):
wgethttps://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.shbashMiniforge3-Linux-x86_64.sh安装时按提示确认许可证、安装目录,建议执行conda init。完成后:
source~/.bashrc conda--version如果不想每次自动进base:
conda config--setauto_activate_basefalse然后创建 Python 3.10 环境(公开仓库 README 和cp310wheel 都按 3.10 来):
conda create-namlnn_toolkit_py310python=3.10-yconda activate amlnn_toolkit_py310 python--version3. 克隆amlnn-toolkit(注意 Git LFS)
仓库里的 x86 wheel用 Git LFS 存的。如果只git clone没装 LFS,后面你会发现.whl只有一百多字节——那是指针文件,不是真正的包。
3.1 安装Git LFS
Ubuntu / Debian:
sudoaptupdatesudoaptinstall-ygitgit-lfsgitlfsinstall3.2 克隆仓库
gitclone https://github.com/Amlogic-NN/amlnn-toolkit.gitcdamlnn-toolkitgitlfs pull3.3 坑一:clone GitHub较慢
直连经常卡在几十 KB/s,甚至超时。可以换镜像试试:
gitclone https://ghproxy.net/https://github.com/Amlogic-NN/amlnn-toolkit.gitcdamlnn-toolkitgitlfs pull注意:镜像站点会变,失效了就换别的代理 / 也可以本机下好再上传服务器或虚拟机。
3.4 检查wheel是否真正下下来了
ls-lhamlnn_toolkit/whl/linux_x86/正常情况类似:
amlnn_toolkit-1.0.0-cp310-cp310-linux_x86_64.whl 约 100MB+ amlnn_toolkit-1.0.0-cp311-...whl amlnn_toolkit-1.0.0-cp312-...whl requirements_x86_64.txt如果.whl只有134B左右,百分之九十九是 LFS 没拉成功,回去再执行:
gitlfsinstallgitlfs pull4. 安装Python依赖
conda activate amlnn_toolkit_py310cdamlnn-toolkit官方 README写得是:
pipinstall-ramlnn_toolkit/whl/linux_x86/requirements_x86_64.txt pipinstallamlnn_toolkit/whl/linux_x86/amlnn_toolkit-1.0.0-cp310-cp310-linux_x86_64.whl实际在安装上,大家不一定能一把梭成功。。
4.1 添加镜像源
网速慢的话,添加阿里云镜像源能加速下载速度,安装会需要一段时间。
网好的可直接装。
pipinstall-ramlnn_toolkit/whl/linux_x86/requirements_x86_64.txt-ihttp://mirrors.aliyun.com/pypi/simple pipinstallamlnn_toolkit/whl/linux_x86/amlnn_toolkit-1.0.0-cp310-cp310-linux_x86_64.whl-ihttp://mirrors.aliyun.com/pypi/simple4.2 坑二:装完ai-edge-torch后,import amlnn报 TF Lite so 缺符号
原因大致是ai-edge-tensorflow和正式版tensorflow==2.20.0打架。处理办法:
python-mpipinstall--force-reinstall --no-deps'tensorflow==2.20.0'-ihttps://pypi.tuna.tsinghua.edu.cn/simple4.3 安装 amlnn wheel
依赖齐了之后再装 wheel。依赖已经手动搞定的话,可以用--no-deps,避免又回去解析 nightly:
python-mpipinstall--no-deps amlnn_toolkit/whl/linux_x86/amlnn_toolkit-1.0.0-cp310-cp310-linux_x86_64.whl验证:
python-c"from amlnn.api import AMLNN; print('amlnn-toolkit import OK')"看到:amlnn-toolkit import OK
就说明这一关过了。
5. 准备 YOLOv8n:.pt→.onnx
5.1 安装 Ultralytics(别把 torch 冲掉,如果已经有对应pt或者onnx模型文件可跳过此步骤)
toolkit 已经钉死torch==2.9.1。如果直接:
pipinstallultralytics它可能顺手把 torch / CUDA 相关包装得乱七八糟。稳一点的话可以执行下面代码:
python-mpipinstall--no-deps ultralytics\-ihttps://pypi.tuna.tsinghua.edu.cn/simple python-mpipinstallmatplotlib pandas seaborn ultralytics-thop\py-cpuinfo'torchvision==0.24.1'nvidia-ml-py polars\-ihttps://pypi.tuna.tsinghua.edu.cn/simple5.2 建工作目录
mkdir-p~/amlnn_workspace/modelsmkdir-p~/amlnn_workspace/calibration/imagescd~/amlnn_workspace/models5.3yolov8n.pt下载
Ultralytics 默认从 GitHub Releases 拉权重,超时的话,可以改用 HF 镜像:
curl-fL-oyolov8n.pt\"https://hf-mirror.com/Ultralytics/YOLOv8/resolve/main/yolov8n.pt"ls-lhyolov8n.pt# 大约 6MB 左右5.4 导出 ONNX(固定 640×640)
amlnn api输入格式支持ONNX、PyTorch、PyTorch pt2、TFLite,这里使用ONNX输入。
第一次转换建议先固定 shape,少给后面编译添变量:
yoloexport\model=yolov8n.pt\format=onnx\imgsz=640\batch=1\dynamic=False\simplify=True\opset=13\nms=FalseAmlogic 官方 YOLOv8 脚本会切这三个内部输出(Ultralytics 版本不同名字可能变):
/model.22/Concat_2_output_0 /model.22/Concat_1_output_0 /model.22/Concat_output_0我用 Ultralytics 8.4.x 导出后,图里仍能看到这三个节点。建议用 Netron 再确认一眼。
6. 准备量化校准图
w8a8需要图片列表。把 jpg/png 放到:
~/amlnn_workspace/calibration/images/生成路径文件:
cd~/amlnn_workspacefind"$(pwd)/calibration/images"-typef\\(-iname'*.jpg'-o-iname'*.jpeg'-o-iname'*.png'\)\|sort>calibration/coco_subset.txtwc-lcalibration/coco_subset.txtheadcalibration/coco_subset.txt校准集对精度的影响以后再单独测。
7. 导出 ADLA(S905X5 / 005)
官方 playground 里有现成的 YOLOv8 转换脚本。可以整个 clone:
gitclone https://github.com/Amlogic-NN/amlnn-model-playground.git# 国内慢就同样用镜像也可以只把examples/yolov8/py/export_adla.py拷到本地,例如:
import argparse import shutil from pathlib import Path import numpy as np from amlnn.api import AMLNN # Normalization constants used for quantization config MEAN = np.array([0, 0, 0], dtype=np.float32) STD = np.array([255, 255, 255], dtype=np.float32) def snapshot_adla_files(search_dir): return {path: path.stat().st_mtime for path in search_dir.rglob("*.adla")} def find_updated_adla_files(search_dir, known_files): current_files = snapshot_adla_files(search_dir) updated_files = [ path for path, mtime in current_files.items() if path not in known_files or mtime > known_files[path] ] return sorted( updated_files, key=lambda path: path.stat().st_mtime, reverse=True, ) def main(): parser = argparse.ArgumentParser(description="Export ONNX to ADLA") parser.add_argument("--onnx", required=True, help="Path to ONNX model") parser.add_argument("--dataset-path", required=True, help="Path to quant dataset") parser.add_argument("--target-platform", required=True, help="Platform ID, e.g. 001, 002, 003") parser.add_argument("--adla", default="../model", help="Optional output .adla path") args = parser.parse_args() search_dir = Path.cwd() known_adla_files = snapshot_adla_files(search_dir) if args.adla else {} amlnn = AMLNN() # NOTE: These node names may be different depending on your model amlnn.load_onnx( model=args.onnx, outputs=[ "/model.22/Concat_2_output_0", # <-- Stride 32 (1x144x13x13 grid) "/model.22/Concat_1_output_0", # <-- Stride 16 (1x144x2x26 grid) "/model.22/Concat_output_0" # <-- Stride 8 (1x144x52x52 grid) ]) amlnn.config( normalization_mean=[MEAN.tolist()], normalization_std=[STD.tolist()], quantized_dtype="w8a8", target_platform=f"PRODUCT_PID0XA{args.target_platform.zfill(3)}", ) amlnn.compile(dataset=args.dataset_path) amlnn.export_adla() if args.adla: new_adla_files = find_updated_adla_files(search_dir, known_adla_files) if not new_adla_files: raise RuntimeError("export_adla did not create or update a .adla file") output_path = Path(args.adla) output_path.parent.mkdir(parents=True, exist_ok=True) if new_adla_files[0].resolve() != output_path.resolve(): shutil.copy2(new_adla_files[0], output_path) print(f"saved: {output_path}") if __name__ == "__main__": main()核心就是四步:
amlnn.load_onnx(...)amlnn.config(...)amlnn.compile(...)amlnn.export_adla()关键配置:
amlnn.config(normalization_mean=[[0.0,0.0,0.0]],normalization_std=[[255.0,255.0,255.0]],quantized_dtype="w8a8",target_platform=f"PRODUCT_PID0XA{target_platform}",)执行:
python ~/amlnn_workspace/scripts/export_adla.py\--onnx~/amlnn_workspace/models/yolov8n.onnx\--dataset-path ~/amlnn_workspace/calibration/coco_subset.txt\--target-platform 005\--adla~/amlnn_workspace/models/yolov8n_s905x5_w8a8.adla成功日志里应出现:
ls-lh~/amlnn_workspace/models/yolov8n_s905x5_w8a8.adla用 adlainfo 看一眼结果
# 仓库路径: amlnn-toolkit/amlnn_toolkit/function_tool/02_adla_info_tool/ cd ~/amlnn-toolkit/amlnn_toolkit/function_tool/02_adla_info_tool chmod +x adlainfo_release ./adlainfo_release -v ~/amlnn_workspace/models/yolov8n_s905x5_w8a8.adla ./adlainfo_release -io ~/amlnn_workspace/models/yolov8n_s905x5_w8a8.adla实测大致是:
- Compile Version:
3.4.4 - Aml Hw Version:
4.0 - 输入:
1×640×640×3,Int8 - 输出:三路检测相关张量,Int8
参考
- Amlogic-NN/amlnn-toolkit
- Amlogic-NN/amlnn-model-playground
- YOLOv8 示例
- Ultralytics Export
- ONNX
本文基于公开仓库个人实测整理,仅供学习记录。工具版本和平台映射可能变化,请以当下 README / release note 为准。欢迎转载,请注明出处。