在显存上使用交换空间

出自 ArchWiki

在极少数情况下,如果您只有极少的 RAM 但有大量的显存,您可以将后者用作交换空间。

MTD 内核子系统

潜在优势

具有 GDDRX SDRAM 或 DDR SDRAM 的显卡可以通过使用内核的 MTD 子系统用作交换空间。拥有 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
注意: 具有多个 GPU 的系统可能在此处有多个条目。

最具潜在优势的是可预取的、64 位的且尺寸最大的区域。

注意: 上面使用的显卡具有 2 GB 的 GDDR5 SDRAM,尽管如上所示,提供的命令并未完全显示或列出全部容量。

显卡需要一部分内存才能运行,因此需要进行一些计算。偏移量很容易计算,因为它是 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 的显存。

注意: 某些驱动程序可能将显存的数字视为 MiB。请参阅相关的手册页。

故障排除

以下命令可能有助于您获取不同空间(如磁盘分区、闪存盘以及可能的显存交换示例)中已使用的交换空间

swapon -s

参见

FUSE 文件系统

警告: 多位用户报告这会导致系统冻结,即使使用了#高内存压力下系统完全冻结中的修复程序也是如此。其他 GPU 管理进程或库可能会被换出,从而导致无法恢复的页面错误。

此方法适用于具有 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 进程本身可能会被交换到 VRAM 交换空间。这会导致完全死锁。一个解决方法是通过 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

参见