Jetson Nano swap扩展
最近在研究摄像头加速技术,终于捡起了一年半不用的jetson nano。一年半前jetson nano很不友好,经常崩溃。现在稳定一点。目前还是仅支持ubuntu18.5.0.这几天尝试用,体验很差,饶了很多弯路。nano提供了两钟(或者三种)升级方案,一种是sd卡烧写,一种是sdkmanager。最找尝试TK1的时候,用sdkmanager,满身伤痕。这次也是因为sdkmanager。总之因为系统的种种问题和配置的问题导致了体验很差,如果不是有良好的心理准备和迎难而上的态度,可能很难深入玩耍。
好了话不多说,进入正题:扩展swap区域。
本文章虽是作者原创,但解决方法来自此处:resizeSwapMemory
在开始之前,先说明一点。我用的是A0版本,不是最新的B0版本。但软件应该区别不大。目前使用的是jetpack4.4.1,系统版本是ubuntu18.04.05 LTS.
1. 改变
如果你使用free -h
查看会发现,系统有4G空间,却只有1.9G左右的swap。网上有一堆教程,大多是重新创建swapfile的。个人感觉方法不够优雅,而且有隐患。这里的方法是修改系统原来用来创建swap的方法,从而扩展1.9G到6G或者更大。我这里按照惯例,分2倍内存大小。
2. 分析
要修改扩展就需要了解之前官方镜像是怎么实现的。
官方使用的是zram的方法,另一种常用的方法是disk partition的方式。这两种方法可以自行搜索。这里转载一段内容:
Zram Swap 是 Linux 内核中采用时间换空间的一种技术。它通过压缩内存(Zram)来作为交换分区,通过压缩比来获取更多可利用的内存空间。该技术目前在各类内存受限的嵌入式系统中,尤其是 Android 手机、电视等设备上广泛采用,本文对此进行了详细介绍。
zram: 是把物理内存的一部分划分出来,把不是常用的内存数据压缩后放到zram里, 用到的时候把数据解压出来, 相当于牺牲了一些cpu效率,变相增大了内存。
磁盘 swap:是把磁盘的一部分作为内存, 对应用来说完全是透明的,相当与增大了内存, 但是缺点很明显, 当用到swap的时候,速度会变的很慢。
之前的很多方法就是上文说的磁盘swap(磁盘分区disk partition)的方式。
可以使用sudo fdisk -l
查看分区情况,比如现在的jetson nano是这样的:
jetson@jetson-desktop:~/Workspace$ sudo fdisk -l
[sudo] password for jetson:
Disk /dev/ram0: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram1: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram2: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram3: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram4: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram5: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram6: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram7: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram8: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram9: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram10: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram11: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram12: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram13: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram14: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/ram15: 8 MiB, 8388608 bytes, 16384 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/loop0: 16 MiB, 16777216 bytes, 32768 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x00000000
Disk /dev/mtdblock0: 4 MiB, 4194304 bytes, 8192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk /dev/mmcblk0: 59.5 GiB, 63864569856 bytes, 124735488 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 6FD14DA8-D37D-4BC5-B42A-C552EF857A6E
Device Start End Sectors Size Type
/dev/mmcblk0p1 7624 124734919 124727296 59.5G Microsoft basic data
/dev/mmcblk0p2 34 289 256 128K Microsoft basic data
/dev/mmcblk0p3 290 1185 896 448K Microsoft basic data
/dev/mmcblk0p4 1186 2337 1152 576K Microsoft basic data
/dev/mmcblk0p5 2338 2465 128 64K Microsoft basic data
/dev/mmcblk0p6 2466 2849 384 192K Microsoft basic data
/dev/mmcblk0p7 2850 3617 768 384K Microsoft basic data
/dev/mmcblk0p8 3618 3745 128 64K Microsoft basic data
/dev/mmcblk0p9 3746 4641 896 448K Microsoft basic data
/dev/mmcblk0p10 4642 5537 896 448K Microsoft basic data
/dev/mmcblk0p11 5538 7073 1536 768K Microsoft basic data
/dev/mmcblk0p12 7074 7201 128 64K Microsoft basic data
/dev/mmcblk0p13 7202 7361 160 80K Microsoft basic data
/dev/mmcblk0p14 7362 7617 256 128K Microsoft basic data
Partition table entries are not in disk order.
Disk /dev/zram0: 494.5 MiB, 518537216 bytes, 126596 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/zram1: 494.5 MiB, 518537216 bytes, 126596 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/zram2: 494.5 MiB, 518537216 bytes, 126596 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disk /dev/zram3: 494.5 MiB, 518537216 bytes, 126596 sectors
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
在上面输出的最后你可以看到我的64G磁盘中有个4段zram分别是zram0~3.可以使用zramctl
来很方便的查看:
jetson@jetson-desktop:~/Workspace$ zramctl
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram3 lzo 494.5M 4K 76B 12K 4 [SWAP]
/dev/zram2 lzo 494.5M 4K 76B 12K 4 [SWAP]
/dev/zram1 lzo 494.5M 4K 76B 12K 4 [SWAP]
/dev/zram0 lzo 494.5M 4K 76B 12K 4 [SWAP]
和上面类似,可以看到每块都是494.5M分区。按照Jetsonhacks的说法是按照下列公式划分的:
mem=$((("${totalmem}" / 2 / "${NRDEVICES}") * 1024))
而这段公式定义在 /etc/systemd/nvzramconfig.sh文件中。文件很短,我们来看看吧:
#!/bin/bash
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
NRDEVICES=$(grep -c ^processor /proc/cpuinfo | sed 's/^0$/1/')
if modinfo zram | grep -q ' zram_num_devices:' 2>/dev/null; then
MODPROBE_ARGS="zram_num_devices=${NRDEVICES}"
elif modinfo zram | grep -q ' num_devices:' 2>/dev/null; then
MODPROBE_ARGS="num_devices=${NRDEVICES}"
else
exit 1
fi
modprobe zram "${MODPROBE_ARGS}"
# Calculate memory to use for zram (1/2 of ram)
totalmem=`LC_ALL=C free | grep -e "^Mem:" | sed -e 's/^Mem: *//' -e 's/ *.*//'`
mem=$((("${totalmem}" / 2 / "${NRDEVICES}") * 1024))
# initialize the devices
for i in $(seq "${NRDEVICES}"); do
DEVNUMBER=$((i - 1))
echo "${mem}" > /sys/block/zram"${DEVNUMBER}"/disksize
mkswap /dev/zram"${DEVNUMBER}"
swapon -p 5 /dev/zram"${DEVNUMBER}"
done
其中NRDEVICES是CPU核心数4,totalmem是内存大小。根据上面的公司可以算出:
mem = (4051068 / 2 / 4)*1024.
乘上1024是为了把4051068的单位K编程byte。所以结果是494.51513671875M。
和输出结果一致。那么聪明的你当然想到了解决办法。
方案
修改公式将/2变为乘以2,这样内存就扩大到了每个区2G,共8G。当然你也可以选择倍数是1.5(注意,你需要先乘3再除以2.我没测试过小数).
# 打开zram文件
sudo vim /etc/systemd/nvzramconfig.sh
# 修改第18行公式为
mem=$((("${totalmem}" * 2 / "${NRDEVICES}") * 1024))
# 保存文件,重启电脑
sudo reboot
free -h
总接
Jetsonhacks的方法更加方便用户操作,但是其实原理很简单,就是将新的文件替换老的文件。我们可以用更直接的方法来替换公式。
感谢Jetsonhacks。
One More Thing
jetson nano的vnc很难用。与raspberry pi的体验差了很多。不建议使用。
另外不建议使用简陋的lightDM桌面。当不需要X桌面时,可以考虑完全关闭。
没有很好的磁盘备份软件,我准备下一步接用rpi-clone项目,做一个jetson-clone工程。敬请期待。多谢。