ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">本篇文章聊聊基于 端侧 AI 计算设备,20~30 瓦功耗运行大模型的算能 AirBox。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;font-size: 22px;font-weight: bold;display: table;margin-top: 2.2em;margin-bottom: 35px;color: rgb(58, 58, 58);border-bottom: 10px solid rgb(241, 173, 42);padding-right: 10px;padding-left: 10px;">写在前面ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">去年的双十二的时候,在群里看到了一张照片,“手掌大小的 NUC”,但是能够跑大模型。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin: 1.5em 8px;color: rgb(58, 58, 58);"> ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">这个草就种下了。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">今年 7 月初的时候,在上海人工智能大会的时候,我在展台上看到了同款“小盒子”,当然,它旁边还有一堆比它算力猛的多的家伙,但是颜值都非常的“朴素”。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin: 1.5em 8px;color: rgb(58, 58, 58);"> ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">于是向朋友“吐槽”,意外的是,不久之后我就收到了这台种草许久的小设备。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin-bottom: 20px;color: rgb(58, 58, 58);">可惜的是,最近一段时间的连续忙碌,让这台设备在我手里起码闲置了两周,最近刚好有一些时间,那么,抓紧时间把这台设备用模型“点亮”吧。ingFang SC", Cambria, Cochin, Georgia, Times, "Times New Roman", serif;margin: 1.5em 8px;color: rgb(58, 58, 58);"> 在这台设备上,跑一张 512x512 的图,生成时间不到 1s,跑一张 512x768 的图,时间也不过 1s 出头。要知道不论是价格还是功耗,它可比“显卡”便宜多了。而且,它应该不光能做图片生成使用,还能折腾一些其他的事情,这些后面有机会我们再来展开。 不过,在实战之前,我们首先需要了解下这台硬件的硬件规格和一些前置知识。 设备硬件规格和相关产品资料虽然朋友发给我的包含了 11 种模型使用场景文档[1]中,出现了 “SG2300X” 类似设备型号的相关文案,应该就是这台设备的主要计算芯片方案的名称。结合一些资料,可以推断这台设备的代号应该是 Airbox。  这台设备使用的芯片之一是Tensor Computing Processor BM1684X[2],看芯片规格页面,能够跑 32 路视频的硬件解码、12路视频的硬件编码,支持 FP32、BF16、FP16、INT8 几种数据类型的模型推理,支持 PCIe3 x16、双千兆以太网口,盒子最大能够支持 16GB 的 DDR4 4266 内存。 结合上面的信息,在互联网上搜索,能够找到的唯一一款类似规格的设备,是Radxa Fogwise Airbox (Fogwise BM168M)[3]。一台今年五月末,在海外由 Radxa 发布的端侧硬件,硬件计算能力和我上面提到的大差不差,开篇特别提到了这个小盒子居然有 32 TOPS 算力。 当然,我认为这个海外的盒子没有我手头这台漂亮,虽然在硬件模型细节上,体验应该是比我手头这台更好的:优化了供电接口、优化了散热方式、优化了接口开槽位置,甚至多给了俩 USB 接口用于硬件能力扩展。不过,硬件设备的颜值就是生产力,那些细节都不重要! 上面提到的文章中提到的 SG2300X 和 BM1684X 本质是相同的一款芯片,所以在折腾的时候,包含这俩硬件的资料,其实都可以参考使用。比如,我们都可以使用SOPHON SDK[4]来完成模型到 TPU 的适配,以及可以在算能官方开发者中心[5]找到最新的 SDK 和 系统刷机包。除了海外产品的 Wiki[6]之外,使用这个 FireFly 的 AI Box 1684X 中文文档[7](不完全推荐,有报错),应该大体上也是 OK 的。  据说有型号的设备支持 M2 / PCIe 的硬盘,不过我使用的版本,可能也是颜值原因,不支持外接存储,暂时只能使用 TF 卡作为扩展或者系统安装使用。 设备供电 设备供电使用的是一块 12V7A 的电源适配器,使用 DC 圆孔连接,电源本身比设备还大不少。默认插电不插设备的时候,功耗 0 瓦,比不少适配器表现好不少(除了 Apple 很少遇到适配器不跑功耗的)。  设备启动后,默认情况设备会跑到 20 瓦,当我们进行推理的时候,设备能够飙到 33 瓦,就配备的电源适配器来看,这个设备应该还有一些额外的潜力。 连接或调试设备设备支持两种调试方式,第一种是使用 TTY,第二种是通过千兆网络。 在安装系统阶段,我个人推荐使用 TTY 的方式来查看安装过程中是否存在问题。当系统安装完毕后,推荐使用普通网络,你可以把设备扔到任何地方,插个网线就能进行管理了,更方便一些。 如果你是 Windows 操作系统,可能需要安装一个串口驱动[8]。如果你是 Linux 或者 macOS,直接使用screen就可以来完成串口设备的连接了。  设备本身自带一个 TYPE-C 口,其实应该叫做 DEBUG 口,使用 TYPE-C 数据线连接设备和电脑后(我使用 Mac 设备),可以通过ls /dev/tty.*来查看是否有新的 tty 设备接入: #ls/dev/tty.* /dev/tty.Bluetooth-Incoming-Port/dev/tty.usbserial-0001
当看到/dev/tty.usbserial-0001时,就能够使用命令设置连接速率来访问设备了: screen/dev/tty.usbserial-0001115200 了解了这些前置知识后,我们就可以开始折腾了。 “完整刷机”:安装新系统我收到的设备,开机后不久,风扇会暴躁启动。根据之前折腾硬件的经验,大概率是因为一些原因卡在启动阶段了。(空白的新设备也是如此) 那么,我首先需要解决硬件的系统问题:刷一个可以启动的系统进去。 获取刷机系统文件结合上文中的信息,我们可以选择在 Radxa 获取到基于Ubuntu Server 20.04 的镜像文件(9.5GB)[9],或者在算能开发者中心找到基于Ubuntu Server 20.04的镜像(15~35GB 资料包,1GB 系统镜像)[10],或者在 FireFly 获取基于Ubuntu 20.04 的镜像文件(2.5GB)[11],或者使用朋友发我的网盘文件(7GB)[12],来完成系统的安装。 我个人推荐使用算能官方开发者中心提供的最新镜像(构建时间 2024-06-24,1GB)[13],小巧、干净。 这些不同尺寸的系统文件镜像(压缩包)中,通常包含以下内容: •Ubuntu Server 20.04 系统•Sophon SDK•较大的镜像包括:预装的 LLM 模型应用、或者某种预装的前端界面(如:CasaOS 或定制界面) 准备刷机使用的 SD 卡(TF卡) 安装系统这里建议使用小容量的 SD 卡,过大容量的 TF 卡无法被格式化为 FAT32,作为引导盘使用。至于卡的类型,我们选择 Class10 以上的就行,如果我们选择比较小的操作系统,那么刷机时间大概只要 3~10 分钟左右(基于慢速 TF 卡)。  你可以参考这篇文章[14],来完成系统盘的准备。也可以参考我的方法,找个 Windows 系统,把 TF 卡格式化成 FAT32,然后将系统文件直接复制进去。  准备好之后,将 TF 卡插到设备上,长按电源键直至绿色指示灯亮起即可(可以短按 + 长按)。 macOS 观察设备输入状态(3~10分钟)上文中提到了如何连接设备,当我们使用screen命令连接设备后 screen/dev/tty.usbserial-0001115200 我们将能够看到系统正在自动的刷入: ... Uncompressedsize:70451200=0x4330000
MMCwrite:dev#0,block#471040,count137600...137600blockswritten:OK
fsreading//boot_emmc-misc.scr 790bytesreadin18ms(42KiB/s) ##Executingscriptat300040000 fsreading//misc.1-of-1.gz 10220bytesreadin19ms(524.4KiB/s)
Uncompressedsize:10485760=0xA00000
MMCwrite:dev#0,block#6561792,count20480...20480blockswritten:OK
fsreading//boot_emmc-rootfs.scr 15788bytesreadin20ms(770.5KiB/s) ##Executingscriptat300040000 bmsavelog6622byteswrittenin17ms(379.9KiB/s) fsreading//rootfs.1-of-27.gz 5940751bytesreadin763ms(7.4MiB/s)
Uncompressedsize:102760448=0x6200000
...
等待一段时间后,我们就能够看到eMMC更新成功的提示,接着就是刷屏的“请移除安装介质并重启设备” 的提示。 ... eMMCupdatedone bmsavelog8191byteswrittenin12ms(666KiB/s) alldone LED'status'notfound(err=-19) LED'error'notfound(err=-19) fsreading//post.scr Failedtoload'//post.scr' LED'status'notfound(err=-19) Pleaseremovetheinstallationmedium,thenreboot LED'status'notfound(err=-19) Pleaseremovetheinstallationmedium,thenreboot LED'status'notfound(err=-19) ...
将设备断电,弹出 TF 卡,并重新启动设备,这个时候,TTY 将重新连接,一段启动日志刷屏后,我们将进入 BOOT 系统,默认情况下会自动继续启动设备,直至进入 Ubuntu 操作系统,如果没有自动启动 Ubuntu,那么我们需要输入boot,稍等片刻,就能够看到熟悉的 Ubuntu 引导过程了。 即使没有自动启动到 Ubuntu,输入boot的这个操作也只需要一次,后续系统就会自动引导了。如果你使用的是1~2GB的镜像,镜像默认的账号密码都是admin或者linaro。 刷机后的设备信息简单扫一下系统识别到的核心设备信息,从 CPU 开始: #lscpu Architecture:aarch64 CPUop-mode(s):32-bit,64-bit ByteOrder ittleEndian CPU(s):8 On-lineCPU(s)list:0-7 Thread(s)percore:1 Core(s)persocket:4 Socket(s):2 VendorID:ARM Model:4 Modelname:Cortex-A53 Stepping:r0p4 CPUmaxMHz:2300.0000 CPUminMHz:1150.0000 BogoMIPS:100.00 VulnerabilityItlbmultihit:Notaffected VulnerabilityL1tf:Notaffected VulnerabilityMds:Notaffected VulnerabilityMeltdown:Notaffected VulnerabilityMmiostaledata:Notaffected VulnerabilityRetbleed:Notaffected VulnerabilitySpecstorebypass:Notaffected VulnerabilitySpectrev1:Mitigation;__userpointersanitization VulnerabilitySpectrev2:Notaffected VulnerabilitySrbds:Notaffected VulnerabilityTsxasyncabort:Notaffected Flags:fpasimdevtstrmaespmullsha1sha2crc32cpuid
TPU 加速卡,可以通过bm-smi命令来获取: #bm-smi +--------------------------------------------------------------------------------------------------+ |LibVersion:0.5.1DriverVersion:0.5.1| +---------------------------------------+----------------------------------------------------------+ |cardNameModeSN|TPUboardTchipTTPU_PTPU_VECCCorrectNTpu-Util| |12V_ATXMaxPboardPMinclkMaxclkFan|Bus-IDStatusCurrclkTPU_CMemory-Usage| |=======================================+==========================================================| |01684X-SOCSOCN/A|0N/AN/AN/AN/AN/AN/A0%| |N/AN/AN/A75M950MN/A|N/AActive950MN/A0MB/8429MB| +=======================================+==========================================================+
+--------------------------------------------------------------------------------------------------+ |Processes:TPUMemory| |TPU-IDPIDProcessnameUsage| |==================================================================================================|
设备直接内置了 Docker,免得我们自己折腾了: #dockerinfo Client: DebugMode:false
Server: Containers:0 Running:0 Paused:0 Stopped:0 Images:0 ServerVersion:19.03.8 StorageDriver verlay2 BackingFilesystem:<unknown> Supportsd_type:true NativeOverlayDiff:true LoggingDriver:json-file CgroupDriver:cgroupfs Plugins: Volume:local Network:bridgehostipvlanmacvlannulloverlay Log:awslogsfluentdgcplogsgelfjournaldjson-filelocallogentriessplunksyslog Swarm:inactive Runtimes:runc DefaultRuntime:runc InitBinary:docker-init containerdversion: runcversion: initversion: SecurityOptions: seccomp Profile:default KernelVersion:5.4.217-bm1684-g27254622663c OperatingSystem:Ubuntu20.04LTS OSType:linux Architecture:aarch64 CPUs:8 TotalMemory:6.755GiB Name:bm1684 ID:RI6R:6SHM:G4SR:7BNU:CB7Z:GCHF:XZ7L:HC7O MTN:4UJL:5G7P:VM7K DockerRootDir:/data/docker DebugMode:false Registry:https://index.docker.io/v1/ Labels: Experimental:false InsecureRegistries: 127.0.0.0/8 LiveRestoreEnabled:false
默认情况下,系统运行的进程和内存容量(6G+)一目了然: top-01:24:55up1min,1user,loadaverage:0.39,0.17,0.06 Tasks:183total,1running,182sleeping,0stopped,0zombie %Cpu(s):0.7us,3.7sy,0.0ni,95.6id,0.0wa,0.0hi,0.0si,0.0st MiBMem:6917.2total,6183.3free,393.5used,340.4buff/cache MiBSwap:0.0total,0.0free,0.0used.6425.6availMem
PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND 1root200167856108007156S0.00.20:04.81systemd 2root200000S0.00.00:00.00kthreadd 3root0-20000I0.00.00:00.00rcu_gp 4root0-20000I0.00.00:00.00rcu_par+ 5root200000I0.00.00:00.00kworker+ 6root0-20000I0.00.00:00.00kworker+ 7root200000I0.00.00:00.04kworker+ 8root0-20000I0.00.00:00.00mm_perc+ 9root200000S0.00.00:00.01ksoftir+ 10root200000I0.00.00:00.04rcu_sch+ 11rootrt0000S0.00.00:00.00migrati+ 12root200000S0.00.00:00.00cpuhp/0 13root200000S0.00.00:00.00cpuhp/1 14rootrt0000S0.00.00:00.00migrati+ 15root200000S0.00.00:00.01ksoftir+ 16root200000I0.00.00:00.00kworker+ 17root0-20000I0.00.00:00.02kworker+
默认情况下,设备内置了 16GB 的存储: df-h FilesystemSizeUsedAvailUse%Mountedon overlay16G79M16G1%/ devtmpfs3.4G03.4G0%/dev tmpfs3.4G03.4G0%/dev/shm tmpfs692M3.0M689M1%/run tmpfs5.0M05.0M0%/run/lock tmpfs3.4G03.4G0%/sys/fs/cgroup /dev/mmcblk0p1128M65M64M51%/boot /dev/mmcblk0p74.2G1.4G2.6G36%/data /dev/mmcblk0p43.6G3.6G0100%/media/root-ro /dev/mmcblk0p516G79M16G1%/media/root-rw /dev/mmcblk0p62.0G199M1.7G11%/opt /dev/mmcblk0p22.9G52M2.8G2%/recovery tmpfs692M4.0K692M1%/run/user/1001
好了,硬件的纸面参数和系统中基础状况都收集到了,我们来折腾 AI 应用。 IO 能力简单测试在折腾之前,我们还可以参考《NUC 折腾笔记 - 储存能力测试[15]》中的“使用 dd 进行顺序文件写测试”,来对设备读写能力有个大概了解: echo"test1G" timesh-c"ddif=/dev/zeroof=/data/ddfilebs=1Mcount=1024oflag=direct&&sync"; rm/data/ddfile;
测试结果,写入 1G 文件,大概需要 23s,实际写速度为 45MB/s。 1024+0recordsin 1024+0recordsout 1073741824bytes(1.1GB,1.0GiB)copied,23.3722s,45.9MB/s
real0m23.398s user0m0.002s sys0m0.251s
为设备配置网络默认情况下,这个小设备的两个网络接口,一个设置为了 DHCP 获取,一个设置为了固定的私有网络 IP 地址(192.168.150.1): #ipaddr ... 3:eth0:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscmqstateUPgroupdefaultqlen1000 link/ether58:c4:1e:e0:21:f2brdff:ff:ff:ff:ff:ff inet6fe80::5ac4:1eff:fee0:21f2/64scopelink valid_lftforeverpreferred_lftforever 4:eth1:<BROADCAST,MULTICAST,UP,LOWER_UP>mtu1500qdiscmqstateUPgroupdefaultqlen1000 link/ether58:c4:1e:e0:21:f3brdff:ff:ff:ff:ff:ff inet192.168.150.1/24brd192.168.150.255scopeglobaleth1 valid_lftforeverpreferred_lftforever inet6fd0a:9b39:bc25:744e:5ac4:1eff:fee0:21f3/64scopeglobaldynamicmngtmpaddrnoprefixroute valid_lft1654secpreferred_lft1654sec inet6fe80::5ac4:1eff:fee0:21f3/64scopelink valid_lftforeverpreferred_lftforever ...
查看网络配置,网卡的定义如下: #cat/etc/netplan/01-netcfg.yaml
network: version:2 renderer:networkd ethernets: eth0: dhcp4:yes addresses:[] optional:yes dhcp-identifier:mac eth1: dhcp4:no addresses:[192.168.150.1/24] optional:yes enp3s0: dhcp4:yes addresses:[] dhcp-identifier:mac optional:yes enp4s0: dhcp4:yes addresses:[] dhcp-identifier:mac optional:yes
为了更高效的使用设备,我们可以做一些调整,比如允许两个端口都联网,连接两个不同的网络出口或者进行端口 Bounding,将两个 1G 网口合并成一个 2G 的虚拟网口: network: version:2 renderer:networkd ethernets: eth0: dhcp4:yes eth1: dhcp4:yes enp3s0: dhcp4:yes addresses:[] dhcp-identifier:mac optional:yes enp4s0: dhcp4:yes addresses:[] dhcp-identifier:mac optional:yes enp6s0: dhcp4:yes addresses:[] dhcp-identifier:mac optional:yes
修改完毕后,我们执行netplan apply来应用修改,稍等几秒,执行命令查看是否获取到了局域网的地址: #ipaddr|grepinet ... inet10.11.12.177/24brd10.11.12.255scopeglobaldynamiceth1 ...
设备能够联网后,我们就可以通过以太网的方式来访问设备了,拔掉 Type-C 数据线,使用ssh admin@设备IP来登录设备即可。 配置更快的软件源默认情况下,设备使用的是 Ubuntu 官方的镜像源。 #cat/etc/apt/sources.list debhttp://ports.ubuntu.com/ubuntu-portsfocalmainuniverse
顺手换成“清华源”,让下载速度能够达到几十MB/s。 sed-is#http://ports.ubuntu.com/ubuntu-ports#https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/#/etc/apt/sources.list 更新 PyPi 和配置镜像源默认版本的 Pip 版本非常低,我们需要对它进行更新,当更新完毕,可以简单设置软件源,来加速后续软件的下载: python3-mpipinstall-ihttps://pypi.tuna.tsinghua.edu.cn/simple--upgradepip pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple
部署 Stable Diffusion 文生图模型AirBox 的算力刚刚好能够支持 Stable Diffusion(TPU 量化版模型)搭配 Control-Net、LCM 完成一秒一张图,运行功耗 20~30瓦,这不比占一张显卡跑图香嘛。在 Radxa 的 Stable Diffusion TPU 文档中,我们能够看到完整的Stable Diffusion 文生图应用部署说明[16]。 需要注意的是,如果你想顺利的部署这个项目。务必保持依赖为下面的版本: pipinstalltorch==2.2.0torchsde==0.2.6transformers==4.29.1tqdm==4.66.4diffusers==0.29.2pillow==10.4.0dfn==1.5.0nasops==0.1.2lark==1.1.9 当我们配置好设备的网络后,就可以来完成这个文生图应用的配置了: #访问设备的数据目录 cd/data #下载应用代码 gitclonehttps://github.com/zifeng-radxa/SD-lcm-tpu.git-bradxa_v0.3.0 #切换工作目录 cdSD-lcm-tpu #创建模型目录 mkdir-pmodels/basic&&cdmodels/basic
#下载预转换模型AbsoluteRealitybmodels下载脚本 wgethttps://github.com/radxa-edge/TPU-Edge-AI/releases/download/sd_v3/tar_downloader.sh #执行下载脚本 bashtar_downloader.sh #将下载内容解压缩 tar-xvfAbsoluteReality_v1.8.1_sd15_original.tar.gz
#切换目录,处理Controlnet和LCM cd/data/SD-lcm-tpu #创建Controlnet的目录(canny) mkdir-pmodels/controlnet&&cdmodels/controlnet #下载Controlnet模型 wgethttps://github.com/radxa-edge/TPU-Edge-AI/releases/download/sd_v3/canny_multize.bmodel
#切换目录,完成依赖软件安装 cd/data/SD-lcm-tpu
pipinstalltorch==2.2.0torchsde==0.2.6transformers==4.29.1tqdm==4.66.4diffusers==0.29.2pillow==10.4.0dfn==1.5.0nasops==0.1.2lark==1.1.9 #运行启动脚本(自动设置环境变量,并执行gr.py) bashrun.sh
当我们运行程序后,稍等片刻就能够看到熟悉的提示: bashrun.sh RunningonlocalURL:http://0.0.0.0:8999
Tocreateapubliclink,set`share=True`in`launch()`.
浏览器访问设备的IP:8999,就能够打开 SD WebUI,开始绘图之旅啦。   关于 Prompt 的生成和优化,如果你感兴趣,可以阅读去年登上 GitHub 热榜的项目《八十行代码实现开源的 Midjourney、Stable Diffusion “咒语”作图工具[17]》。 最后原本以为这台设备的折腾时间会非常“短平快”,没想到因为依赖的问题,拉着朋友一起折腾了一两个小时,感谢朋友的时间投入。希望后面开源社区越来越好,社区用户越来越多之后,这些踩坑的事情,能够越来越少。 如果这个设备只是跑个 Demo 就完事,未免太浪费了,接下来我会在一些有趣的场景中,使用这个小东西,来完成一些高性价比的事情。 --EOF |