在显存上进行交换
在极少数情况下,如果您拥有极少的 RAM 和大量的显存,您可以将后者用作交换空间。
MTD 内核子系统
潜在优势
使用内核的 MTD 子系统,可以将配备 GDDRX SDRAM 或 DDR SDRAM 的显卡用作交换空间。拥有 256 MB 或以上独立显存且系统内存(DDRX SDRAM)有限的系统可能从这种设置中获益最多。
- 这不适用于闭源驱动程序。
- 除非您的显卡驱动程序可以设置为使用比检测到的显存更少的内存,否则当您尝试使用同一部分 RAM 来存储纹理和交换空间时,Xorg 可能会崩溃。使用允许您覆盖显存设置的视频驱动程序应该可以提高稳定性。
预先设置
您必须加载模块,指定与您的显卡上的 RAM 相对应的 PCI 地址范围。
要查找可用的内存范围,请运行以下命令并查找 VGA 兼容控制器部分(请参见下面的示例)。
$ lspci -vvv
01:00.0 VGA compatible controller: NVIDIA Corporation GK104 [GeForce GTX 670] (rev a1) (prog-if 00 [VGA controller]) Subsystem: ASUSTeK Computer Inc. Device 8405 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0 Interrupt: pin A routed to IRQ 57 Region 0: Memory at f5000000 (32-bit, non-prefetchable) [size=16M] Region 1: Memory at e8000000 (64-bit, prefetchable) [size=128M] Region 3: Memory at f0000000 (64-bit, prefetchable) [size=32M] Region 5: I/O ports at e000 [size=128] [virtual] Expansion ROM at f6000000 [disabled] [size=512K] Capabilities: <access denied> Kernel driver in use: nvidia Kernel modules: nouveau, nvidia
最有可能受益的区域是可预取的、64 位的且尺寸最大的区域。
显卡需要一些内存才能正常工作,因此需要进行一些计算。偏移量很容易以 2 的幂次方计算。显卡应使用地址范围的开头部分作为帧缓冲区,用于纹理等。但是,如果有限制,或者如本文开头所述,如果两个程序尝试写入相同的扇区,则可能会出现稳定性问题。
例如:对于总共 256 MB 的显存,公式为 2^28(2 的 28 次方)。大约 64 MB 可以留给显存,因此显存交换空间的使用起始范围将使用公式 2^26 计算。
使用上面的数字,您可以取差值并确定一个合理的范围用作交换内存。为正常功能留下 2^24 (32M)(更少也可以正常工作)
设置
配置 phram 模块(3.x 内核使用 slram 模块)
/etc/modprobe.d/modprobe.conf
options phram phram=VRAM,0xStartRange,0xUsedAmount
在启动时加载模块
/etc/modules-load.d/vramswap.conf
phram mtdblock
创建一个 systemd 服务
/usr/lib/systemd/system/vramswap.service
[Unit] Description=Swap on Video RAM [Service] Type=oneshot ExecStart=/usr/bin/mkswap /dev/mtdblock0 ExecStart=/usr/bin/swapon /dev/mtdblock0 -p 10 ExecStop=/usr/bin/swapoff /dev/mtdblock0 RemainAfterExit=yes [Install] WantedBy=multi-user.target
mtdblock
设备,请使用 cat /proc/mtd
查找名称为 VRAM 的 mtdblock
。Xorg 驱动配置
为了保持 X 的稳定性,需要告知您的视频驱动程序使用少于检测到的显存。
/etc/X11/xorg.conf.d/vramswap.conf
Section "Device" Driver "radeon" # or whichever other driver you use VideoRam 32768 #other stuff EndSection
上面的示例指定您使用 32 MB 的显存。
故障排除
以下命令可能有助于您获取不同空间(如磁盘分区、闪存盘)以及可能在本例中显存交换空间中已使用的交换空间。
swapon -s
参见
FUSE 文件系统
此方法适用于支持 OpenCL 的硬件,使用 FUSE 文件系统作为交换文件的后端。有关更多信息,请参阅 GPGPU。
设置
首先,安装 vramfs-gitAUR。然后,创建一个空目录作为挂载点(例如 /tmp/vram
)。
现在运行以下命令以设置 vramfs 和交换文件。
# vramfs /tmp/vram 256MB -f # Substitute 256M with your target vramfs size # mkswap -U clear --size 200M --file /tmp/vram/swapfile # Substitute 200 with your target swapspace size in MiB
您的交换空间现在应该已准备就绪。运行 swapon
进行检查。
有关更多信息,请参阅 Swap#交换文件。
/tmp/vram
用作临时存储,很像 Tmpfs。设置 swappiness
在显存上进行交换的情况下,增加 swappiness 可能是个好主意。当 VRAM 交换文件的随机 I/O 速度明显快于随机磁盘 I/O 时,情况尤其如此,因为缓存磁盘读取的好处将超过交换的成本。例如,如果您的随机磁盘 I/O 速度与 VRAM 交换 I/O 速度相同,则应将 swappiness 设置为 100。如果 VRAM 交换 I/O 速度比磁盘 I/O 速度快 2 倍,则应将 swappiness 设置为 133。有关如何正确计算 swappiness 值的更多信息,请参阅内核文档。
故障排除
swapon: /tmp/vram/swapfile: 跳过 - 它似乎有空洞。
创建的交换文件不是连续的。可以设置环回设备来解决此问题。
# cd /tmp/vram # LOOPDEV=$(losetup -f) # truncate -s 4G swapfile # replace 4G with target swapspace size, has to be smaller than the allocated vramfs # losetup $LOOPDEV swapfile # mkswap $LOOPDEV # swapon $LOOPDEV
高内存压力下系统完全冻结
有时,在极高的内存压力下,vramfs
进程本身可能会被交换到显存交换空间。这会导致完全死锁。一种解决方法是通过 cgroups 使该进程不可交换,方法是通过 systemd 文件启动它
/etc/systemd/system/vramswap.service
[Unit] Description=Set up swap in VRAM After=default.target [Service] Type=oneshot RemainAfterExit=yes # Change /root/vramswap.sh to a path to a script that performs all the necessary setup ExecStart=/root/vramswap.sh TimeoutStartSec=0 # Prevent swapping MemorySwapMax=0 [Install] WantedBy=default.target