2024-12-13 01:31:47
近日OpenWrt官方出了台MT7981的路由器,就是价格非常感人,不过看在它带RTC、POE、GPIO、nor/nand双启动、type-c转串口、还有M2 nvme槽(以及情怀)的份上还是买了一台玩玩。这机器最大的短板就是弱鸡的双核1.3G的MT7981,跑NAT + WiFi到千兆就几乎吃满了CPU(无offload情况),所以想着超个频。
前置知识:MT7981是一个ARMv8-A SoC,一般使用ARM Trusted Firmware(ATF)方式启动,启动顺序为:BL1(BOOT ROM)-> BL2 -> BL31 -> U-boot -> Linux Kernel,BL位于SoC内的ROM,本机从BL2开始位于外置SPI NAND Flash中(通过切换开关进入恢复模式时会使用SPI NOR Flash)。BL2包含了诸多SoC设备初始化代码,其中包含ARMPLL的初始化代码,其为CPU提供高速时钟(PLL初始化前CPU直接使用外部晶振的40MHz时钟)
参考了恩山论坛里的帖子:MT798X CPU超频1.65G/一键修改无线最大功率方法,不过里面的nand固件只有开NMBM(一种NAND Flash坏快管理机制)的,这台机器的主线OpenWrt不使用NMBM,所以用不了。于是自己研究了下,发在这里以供参考,其他没NMBM的nand理论上也能用(但请先确定自己的环境能成功救砖bl2再刷)。
我手里这台能从1.3GHz超到1.7GHz,跑源里的coremark能从4400分提高到5750分。之后再到1.76G时无线高负载时会崩溃重启,到1.8GHz时开机到一半就会死机,大概是这SoC的极限了,求稳可以只超到1.6GHz(此时coremark为5400分)。
方法简而言之就是修改bl2的pll初始化代码,源码位置:arm-trusted-firmware/plat/mediatek/mt7981/drivers/pll/pll.c (mtk-openwrt/arm-trusted-firmware),需要修改其中PLL的频率值和分频值
以下是详细步骤:
./build_dir/target-aarch64_cortex-a53_musl/arm-trusted-firmware-mediatek-mt7981-spim-nand-ubi-ddr4/arm-trusted-firmware-mediatek-2024.01.17~bacca82a/plat/mediatek/mt7981/drivers/pll/pll.c
文件(注意这样直接编辑的话make clean后这个文件的改动就丢了,标准做法是写个patch,这里只是图省事),其他机型请根据实际情况修改路径中的spim-nand-ubi-ddr4,找到正确的软件包/* Set PLL frequency */
这段,具体修改后的代码和解释如下: /* Set PLL frequency */
// 241208: overclock hack
NOTICE("THIS IS AN OVERCLOKING BL2!\n");
NOTICE("set arm freq to 1.60 GHz:\n");
// 设置频率值,SDMPLL fractional mode,这里只需修改高8位
// 原始为2分频,0x82 = 130,实际对应1.3GHz:
// mmio_write_32(ARMPLL_CON1, 0x82000000); /* 1.3G */)
// 由于这个值再大一些的话会设置失败,所以我们要使用1分频(不分频):
// 例如:0x50 = 80,此时对应1.6G; 0x55 = 85,对应1.7G,一次类推
mmio_write_32(ARMPLL_CON1, 0x50000000); /* 1.6G */
// mmio_write_32(ARMPLL_CON1, 0x55000000); /* 1.7G */
NOTICE("ARMPLL_CON1 = 0x%x\n", mmio_read_32(ARMPLL_CON1));
// 设置分频比,原始为2分频,还有个注释掉的4分频(用这个就是650MHz):
// //mmio_setbits_32(ARMPLL_CON0, 0x124); /* divider for 650M */
// mmio_setbits_32(ARMPLL_CON0, 0x114); /* divider for 1.3G */
// 修改为不分频,这个寄存器的4~6位(从0开始数)为分频值,由于默认是001(2分频),这里要将其清零(1分频),然后再设置其余bits
mmio_clrbits_32(ARMPLL_CON0, 0x70); /* divider for >1.3G */
mmio_setbits_32(ARMPLL_CON0, 0x104);
NOTICE("ARMPLL_CON0 = 0x%x\n", mmio_read_32(ARMPLL_CON0));
bin/targets/mediatek/filogic/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin到nand
中的bl2分区:
opkg install mtd kmod-mtd-rw
insmod mtd-rw.ko i_want_a_brick
mtd write /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
mtd verify /tmp/openwrt-mediatek-filogic-openwrt_one-snand-preloader.bin bl2
reboot
下面是我编译的bl2:
对于OpenWrt One,可以直接刷入;
对于其他spim-nand-ubi-ddr4且非NMBM机型,也可以尝试直接刷入;
对于NMBM机型,请使用之前论坛里大佬发的超频bl2,也可以自己参考此方法编译,不要直接刷这个版本;
免责声明:由于刷bl2和超频有不小风险,请在刷之前一定要保证有救砖手段;同时超频会导致功耗增加,会增加供电电路的负荷,会有硬件损坏或者折寿的风险。
参考资料:https://mirror2.openwrt.org/docs/MT7981B_Wi-Fi6_Platform_Registers_Open_Part1_V1.0.pdf ,Page 310~311:
2024-07-04 21:24:10
400多块买了个便宜的单盘位DS118白群晖当容灾备份机器用,到手发现这个机型居然不支持创建btrfs的存储空间,这就十分难绷了,毕竟数据校验、快照等功能都用不了。
然后发现,尽管最近一代的新品在售的机器都支持btrfs了,但直到2020年群晖NAS的很多低端型号都不支持btrfs,其中20、19、18系列就包括:DS420j,DS220j,DS120j,DS419slim,DS119j,DS418j,DS218play,DS218j,DS118
尽管这些机型的配置确实不高,但btrfs其实也不是会费太多资源的东西,DS118这种机型完全能够支持,毕竟同为RTD1296 CPU的DS218或者同为1G内存的机器DS216+都是支持btrfs的,这么搞大概只是为了差别对待。
实际上,群晖在这些型号上用的系统都是差不多的,底层其实都带有btrfs功能,只是在Web UI上被隐藏了,这些功能的差异被定义在了/etc.defaults/synoinfo.conf
中,因此只需要打开SSH功能,连接后执行sudo vim /etc.defaults/synoinfo.conf
,加入以下内容即可:
support_btrfs="yes"
support_btrfs_dedupe="yes"
support_iscsi_btrfs_lun="yes"
support_share_snapshot="yes"
support_share_quota="yes"
support_share_user_quota="yes"
support_dr_snap="yes"
support_dr_replica="yes"
max_btrfs_snapshots="65536"
max_snapshot_per_lun="256"
max_snapshots_per_share="1024"
max_dr_replica="64"
max_sdr_replica="64"
若不会使用vim,也可以使用winscp等软件。此时btrfs存储池便可以被创建和使用,但若想使用群晖的快照套件还需要继续操作。
DSM 7的快照功能需要使用套件SnapshotReplication和其依赖ReplicationService,然而这两个套件默认无法在不支持btrfs的机型上安装,但我们可以通过暂时修改机型的方式来强行安装,然后修改软件包信息。
1. 首先找到一个相似架构且支持btrfs的机器,比如对于我的DS118,我找到了DS218,然后在 群晖官网 -> DS218下载中心 -> DSM 套件 中找到SnapshotReplication和ReplicationService的安装包,上传到home目录中。
2. 编辑/etc.defaults/synoinfo.conf
,修改synobios和unique字段中的机型,例如synobios=”ds118″和unique=”synology_rtd1296_ds118″中的“ds118”改为“ds218”,然后保存。注意:修改机型后,一定要在稍后改回来,期间不要重启,否则系统会无法启动。
3. 安装软件包,在终端中执行(.spk文件的文件名按实际修改):
sudo synopkg install ReplicationService-ds218-1.3.0-0409.spk
sudo synopkg start ReplicationService
sudo synopkg install SnapshotReplication-ds218-7.4.5-1698.spk
sudo synopkg start SnapshotReplication
4. 重要:恢复synoinfo.conf
中的机型修改
5. 此时套件虽然已经安装,但机型不匹配,会提示套件损坏,需要我们修改已安装软件包的信息,依次修改下面两个文件:
/var/packages/ReplicationService/INFO
/var/packages/SnapshotReplication/INFO
找到类似model="synology_rtd1296_ds218"
的行,修改为机器的真实型号,然后重启,即可正常使用SnapshotReplication进行快照。
如果你这样做后依然无法创建快照,请尝试以下命令(homes为共享文件夹名称,可修改),观察快照能否被创建,或是否有报错:
sudo sh -x synosnapschedtask.sh local share homes
玩过黑群晖的都知道,除了SA6400机型用的Linux内核版本是5.10.55(2021年发布)外,其他机型都还在使用上古4.4.302内核(2016年发布),然而在4.4老内核下,btrfs的压缩功能并不支持zstd算法,因此99%的白群晖NAS的文件系统压缩功能都是快速但效果较差的lzo,包括那些同样上万的机型(不100%确定,群晖毕竟对btrfs进行了不少魔改,也有可能backport了zstd的功能,其他机型的朋友可以看下synoinfo.conf是否包含btrfs_default_compression="zstd"
的配置)。
对于黑群晖而言,也有多了一个用SA6400机型的理由。
2024-06-24 15:29:51
2024/07/24 UPDATE: 最新版的群晖Photos APP似乎已经修复/缓解了此问题
这是由于iOS设备(比如iPhone)的空间不足,使App无法转存较大文件导致的。在iCloud中照片/视频大小较大时,尽管在设置中可能会看到还有大量的剩余空间,但实际上是一种“已占用但可被释放”的状态。卸载一些大App或删除一些照片/视频能够解决,但如果不想这样做的话,可以使用下方的方法强制iOS去释放一些空间(iPhone 13 Pro测试可用):
手机打开 相机,切换到视频,开启“ProRes HDR”录制,此时会提示一个很短的“最长时间”和“正在释放资源”。等待一段时间后,当“最长时间”上升到5分钟左右时,群晖Photos即可正常工作。
2024-04-08 05:49:33
(更新Roofline图)在笔记本市场中,Intel Ultra系列和AMD 8000系列不约而同的加入了集成NPU作为卖点(甚至对于AMD而言,是其7000系到8000的几乎唯一变化),各路数码新闻中鼓吹最多的便是所谓“AIPC”概念,但却往往对其NPU的具体用法语焉不详,或者将一些实际使用核显进行的推理归功于NPU。
由于本人近日购入了Intel Core Ultra CPU的笔记本,外加科研需要,对其集成NPU进行了一些调研。
省流:通常跑AI推理的实用性不如核显,目前仅支持静态shape的模型,因此无法做LLM推理,通常只做AI抠图这类简单任务。目前最大的用途是Win11自带的“工作室”效果功能,包含摄像头背景虚化、眼神接触、自动缩放取景三个功能,虽然这些CPU/GPU也能跑,但或许用NPU功耗更低。
设备:华硕 ROG 幻16 air (GU605),CPU:Intel Core Ultra 9 185H
打开Intel官网中Ultra 9 185H的资料,其对NPU的描述如下:
注意最后一行,由于OpenVINO是Intel官方的推理框架,后续我们将用它来测试,OpenVINO显然是支持Ultra的NPU的,相关文档如下:https://docs.openvino.ai/2024/openvino-workflow/running-inference/inference-devices-and-modes/npu-device.html,可以看到Ultra中NPU的实际型号为NPU 3720
测试环境实用Win11,其自带NPU的驱动(Linux下则需要自行编译),OpenVINO使用pip方式安装,具体请参考官方文档,注意其并非所有安装方式都有NPU支持。
使用如下代码检测NPU,并打印其硬件属性:
import openvino as ov
import openvino.properties as ovp
print(f"{ov.__version__ = }")
core = ov.Core()
print(f"{core.available_devices = }")
DEVICE = "NPU"
if DEVICE in core.available_devices:
print(f"- {DEVICE} found")
supported_properties = core.get_property(DEVICE, ovp.supported_properties)
for p, w in supported_properties.items():
try:
print(f"{p:>40} ({w}) = {core.get_property(DEVICE, p)}")
except Exception as e:
print(f"{p:>40} ({w}):", e)
else:
print(f"- {DEVICE} not found")
在我的设备上输出如下:
ov.__version__ = '2024.0.0-14509-34caeefd078-releases/2024/0'
core.available_devices = ['CPU', 'GPU.0', 'GPU.1', 'GPU.2', 'GPU.3', 'NPU']
- NPU found
AVAILABLE_DEVICES (RO) = ['3720']
CACHE_DIR (RO) =
CACHING_PROPERTIES (RO) = {'DEVICE_ARCHITECTURE': 'RW', 'NPU_COMPILATION_MODE_PARAMS': 'RW', 'NPU_DMA_ENGINES': 'RW', 'NPU_DPU_GROUPS': 'RW', 'NPU_COMPILATION_MODE': 'RW', 'NPU_DRIVER_VERSION': 'RW', 'NPU_COMPILER_TYPE': 'RW', 'NPU_USE_ELF_COMPILER_BACKEND': 'RW'}
DEVICE_ARCHITECTURE (RO) = 3720
DEVICE_ID (RW) =
DEVICE_UUID (RO) = <已打码>
ENABLE_CPU_PINNING (RW) = False
EXCLUSIVE_ASYNC_REQUESTS (RW) = False
FULL_DEVICE_NAME (RO) = Intel(R) AI Boost
INTERNAL_SUPPORTED_PROPERTIES (RO) = {'CACHING_PROPERTIES': 'RW'}
LOG_LEVEL (RW) = Level.NO
MODEL_PRIORITY (RW) = Priority.MEDIUM
NPU_BACKEND_NAME (RO) = LEVEL0
NPU_COMPILATION_MODE (RW) =
NPU_COMPILATION_MODE_PARAMS (RW) =
NPU_COMPILER_TYPE (RW) = DRIVER
NPU_DEVICE_ALLOC_MEM_SIZE (RO) = 0
NPU_DEVICE_TOTAL_MEM_SIZE (RO) = 33554432
NPU_DMA_ENGINES (RW) = -1
NPU_DPU_GROUPS (RW) = -1
NPU_DRIVER_VERSION (RO) = 1688
NPU_MAX_TILES (RW) = -1
NPU_PLATFORM (RW) = AUTO_DETECT
NPU_PRINT_PROFILING (RW) = NONE
NPU_PROFILING_OUTPUT_FILE (RW) =
NPU_PROFILING_TYPE (RW): Unable to convert function return value to a Python type! The signature was
(self: openvino._pyopenvino.Core, device_name: str, property: str) -> object
NPU_STEPPING (RW) = -1
NPU_USE_ELF_COMPILER_BACKEND (RW) = AUTO
NUM_STREAMS (RO) = 1
OPTIMAL_NUMBER_OF_INFER_REQUESTS (RO) = 1
OPTIMIZATION_CAPABILITIES (RO) = ['FP16', 'INT8', 'EXPORT_IMPORT']
PERFORMANCE_HINT (RW) = PerformanceMode.LATENCY
PERFORMANCE_HINT_NUM_REQUESTS (RW) = 1
PERF_COUNT (RW) = False
RANGE_FOR_ASYNC_INFER_REQUESTS (RO) = (1, 10, 1)
RANGE_FOR_STREAMS (RO) = (1, 4)
SUPPORTED_PROPERTIES (RO) = {'AVAILABLE_DEVICES': 'RO', 'CACHE_DIR': 'RO', 'CACHING_PROPERTIES': 'RO', 'DEVICE_ARCHITECTURE': 'RO', 'DEVICE_ID': 'RW', 'DEVICE_UUID': 'RO', 'ENABLE_CPU_PINNING': 'RW', 'EXCLUSIVE_ASYNC_REQUESTS': 'RW', 'FULL_DEVICE_NAME': 'RO', 'INTERNAL_SUPPORTED_PROPERTIES': 'RO', 'LOG_LEVEL': 'RW', 'MODEL_PRIORITY': 'RW', 'NPU_BACKEND_NAME': 'RO', 'NPU_COMPILATION_MODE': 'RW', 'NPU_COMPILATION_MODE_PARAMS': 'RW', 'NPU_COMPILER_TYPE': 'RW', 'NPU_DEVICE_ALLOC_MEM_SIZE': 'RO', 'NPU_DEVICE_TOTAL_MEM_SIZE': 'RO', 'NPU_DMA_ENGINES': 'RW', 'NPU_DPU_GROUPS': 'RW', 'NPU_DRIVER_VERSION': 'RO', 'NPU_MAX_TILES': 'RW', 'NPU_PLATFORM': 'RW', 'NPU_PRINT_PROFILING': 'RW', 'NPU_PROFILING_OUTPUT_FILE': 'RW', 'NPU_PROFILING_TYPE': 'RW', 'NPU_STEPPING': 'RW', 'NPU_USE_ELF_COMPILER_BACKEND': 'RW', 'NUM_STREAMS': 'RO', 'OPTIMAL_NUMBER_OF_INFER_REQUESTS': 'RO', 'OPTIMIZATION_CAPABILITIES': 'RO', 'PERFORMANCE_HINT': 'RW', 'PERFORMANCE_HINT_NUM_REQUESTS': 'RW', 'PERF_COUNT': 'RW', 'RANGE_FOR_ASYNC_INFER_REQUESTS': 'RO', 'RANGE_FOR_STREAMS': 'RO', 'SUPPORTED_PROPERTIES': 'RO'}
使用fp16精度,batchsize = 1,重复2000次推理,单次耗时如下:
avg latency = 3.462ms
根据估计的ResNet-50的计算量,其达到的roofline性能大致如下(不准确,仅预估):
RESNET50_M_FLOP = 8206.520 # approximate RESNET50_M_MEM_RW = 105.763 # approximate avg latency = 0.0034620463848114014 reached GFLOP/s: 2370.4246 reached GB/s: 30.5493
达到的fp16性能约为2.35 TFLOP/s,由于是bs=1的推理,离上限值应该还是有不小距离的
功耗的话,用HWInfo64可看到“System Agent Power”在推理时从4w左右增加到10w左右,即6w,不确定这其中是否都是NPU的功耗,否则这个能效表现其实一般。不过在打开全部的“Windows工作室效果”时,System Agent功耗仅上升了1~2w,此时任务管理器中NPU利用率约为46%
这是多个模型在其上的测试,达到的FLOP/s和内存带宽基于理论估计,模型列表如下,不存在则表示(在当时)尚无法成功运行。
可以看出,其优化程度较差,远远无法跑到理论性能fp16: 5.7 TFLOP/s, int8: 11.5TOP/s(计算方法:2048 fp16 MACs or 4096 int8 MACs per cycle @ 1.4GHz)。也有文章指出,其可能无法利用全部的内存带宽,具有远远更低的内存墙,但依然无法解释为何ResNet-34的性能也很低。
Intel Core Ultra 笔记本处理器集成NPU初探(Intel AI Boost)最先出现在WuSiYu Blog。
2023-08-06 04:49:07
这里的背景是OpenWRT作为旁路由(aka. 旁路网关,单臂路由,透明网关等),没有一个太准确的叫法,具体的指另一台“主路由”连接公网并作NAT,OpenWrt不启用NAT,用户设备的上行流量先经过OpenWrt旁路由转发到“主路由”,下行时流量直接通过由主路由发送到用户设备,不经过OpenWrt旁路由。主要优点在于下行带宽不会受OpenWrt性能的影响,且OpenWrt设备故障或维护时,可手动(或配置自动)切换到主路由。(OpenWRT旁路由可以是单臂路由,也可以有另一根独立的线路连接到主路由,避免带宽限制,如我之前的文章)
但由于上行和下行的通路不同,仅有部分流量会经过OpenWrt,会导致TCP的conntrack出现问题。
具体表现是:已经正确设置了路由,且能用户设备能ping通外网,但对外进行TCP不通,若在用户设备上抓包分析会看到:
不难看出,这是由于客户端发送的ACK在中途被丢弃了,使得虽然客户端认为TCP连接已经建立,但在服务端看来没有,因此客户端发送的payload不会被确认,而服务器则会重传SYN + ACK,继续等待客户端的ACK。
这种现象和OpenWrt的conntrack有关,由于服务器回应的SYN + ACK没有经过OpenWrt,使得OpenWrt没有正确追踪TCP连接。在一些特定情况下,OpenWrt认为客户端后续的数据包是“无效数据包”,并丢弃,包括客户端发送的ACK。
在OpenWrt中解决的方法也很简单,首先在“防火墙”页面中关闭“丢弃无效数据包”:
其次,若OpenWrt通过独立线路(在防火墙的WAN Zone)连接主路由,则在一些特定情况下(比如因为一些组网需求,对一些内网网段开启了masquerade),还要打开WAN Zone – 编辑 – 连接追踪设置 – 允许“无效”流量,如下图:
具体conntrack的工作方式和该问题的出现条件,有待进一步验证
2023-07-09 22:29:09
当你的设备同时带有WiFi和有线网时,你就会希望让系统优先使用有线网,一些系统(比如使用NetworkManager的)会自动完成这件事,但DietPi并没有。
各种Linux的网络配置方案会各不相同,比如桌面Linux和新一些的服务器Linux会使用较为现代的NetworkManager,Ubuntu搞过一个netplan,树莓派官方系统Raspbian直接用dhcpcd来管理网络,而DietPi使用Debian传统的/etc/network/interface(ifupdown),这篇文章的方法也适用于其他使用/etc/network/interface配置方案的系统。
首先编辑/etc/network/interface
,为接口设置metric值,格式类似metric 100
,数字越小表示表示优先级越高,DietPi中修改完类似如下(注意该文件在dietpi-config中调整网络接口设置后会被覆盖):
root@DietPi:~# cat /etc/network/interfaces
# Location: /etc/network/interfaces
# Please modify network settings via: dietpi-config
# Or create your own drop-ins in: /etc/network/interfaces.d/
# Drop-in configs
source interfaces.d/*
# Ethernet
allow-hotplug eth0
iface eth0 inet dhcp
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
#dns-nameservers 192.168.10.2
metric 100
# WiFi
allow-hotplug wlan0
iface wlan0 inet dhcp
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
#dns-nameservers 192.168.10.2
pre-up iw dev wlan0 set power_save off
post-down iw dev wlan0 set power_save on
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
metric 600
此外,经过测试,这里的metric值不会对本地网络路由中的metric生效(下面的后两行),导致在访问内网机器时,(甚至是ssh 内网ip时的回程),仍然可能使用错误的网卡:
root@DietPi:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default openwrt 0.0.0.0 UG 100 0 0 eth0
default openwrt 0.0.0.0 UG 600 0 0 wlan0
192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.10.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
解决方法是安装ifmetric
软件包,但我们不需要用这个命令其手动设置metric,而是ifmetric
会在接口启动时自动根据/etc/network/interface中的配置进行设置(软件包提供了/etc/network/if-up.d/ifmetric)。
随后重启网络服务,可以发现metric被正确设置了:
root@DietPi:~# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default openwrt 0.0.0.0 UG 100 0 0 eth0
default openwrt 0.0.0.0 UG 600 0 0 wlan0
192.168.10.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
192.168.10.0 0.0.0.0 255.255.255.0 U 600 0 0 wlan0