如何增加 Ubuntu 的虚拟内存和/或 Matlab 交换空间?

如何增加 Ubuntu 的虚拟内存和/或 Matlab 交换空间?

情况:修复Out of MemoryUbuntu Matlab 中的错误
目标:在外部 HDD/SSD 上分配一些虚拟内存和/或交换;读/写速度从 20 GBps 降低到 0.1 GBps,没问题!
术语:交换和虚拟内存这里

不,交换和虚拟内存完全不同。例如,内存映射 1GB 文件会使用额外的 1GB 虚拟内存,但交换的使用不会发生变化。交换是一种后备存储形式。虚拟内存的许多用途与后备存储无关。(并且有的系统有虚拟内存而没有交换,也有的系统有交换但没有虚拟内存。)

消费者硬件有限,所以我需要使用更多虚拟内存和/或与外部硬盘交换。Matlab 说的是交换内存(TODO 不包括虚拟内存?)

Linux 系统 — 使用mkswapswapon命令更改交换空间。

系统特点

  • 你可以通过以下方式查看你拥有的数量swapon -s

    Filename                Type        Size    Used    Priority
    /dev/sda3               partition   8326140 0       -1
    
  • Matlab 的配置

    % https://stackoverflow.com/a/35971040/54964
    com.mathworks.services.Prefs.setIntegerPref('JavaMemHeapMax', 2048); % MB
    
    % TODO cannot find ways how to put Matlab use /dev/sda3
    
  • 所以你看我的 Matlab 没有使用它。我Out of Memory在 Matlab 中遇到大矩阵时收到错误。我无法将reshape矩阵转换为向量并编写并行代码。所以我想使用虚拟内存,因为我需要完成工作;速率并不重要。

伪代码

  1. 创建交换、启动 MATLAB 并在 MATLAB 退出时删除交换的 Shell 脚本。(迈克尔·霍曼
  2. 在外部硬盘上启用交换。如何使用sudo swapon -a
  3. 启动 Matlab。
  4. 把 Matlab 使用交换起来。
  5. 当 Matlab 退出时删除交换。

Micheal 脚本中的临时交换、运行客户端和关闭/删除交换

情况:无法控制设置环境 (1)、运行 Matlab (2) 和关闭环境 (3)
脚本中的错误

#!/usr/bin/env bash

# https://stackoverflow.com/a/69808/54964
set -e 
# TODO How to do swapoff if any error?

SWAP_FILE="/media/masi/SamiSwapVirtual/.swap_file_20.7.2016"
SIZE_MB=16000
TO_RUN="matlab"

dd if="/dev/zero" of=${SWAP_FILE} bs="1M" count=${SIZE_MB} status="progress"
mkswap ${SWAP_FILE}
chmod 0600 ${SWAP_FILE}
sudo chown 0.0 ${SWAP_FILE} # https://unix.stackexchange.com/a/297153/16920
sudo swapon -v ${SWAP_FILE}
echo "Swap enabled. Press enter to continue"; read
${TO_RUN}
echo "I will remove the swap. Press enter to continue"; read
sudo swapoff -v ${SWAP_FILE}
rm -vf ${SWAP_FILE}

迭代 1,采用 Transcend 25M3 1 TB,使用率不高,文件系统ext4

  1. 启动脚本后的日志

    sh start_matlab_with_swap.sh 
    16000+0 records in
    16000+0 records out
    16777216000 bytes (17 GB, 16 GiB) copied, 134.489 s, 125 MB/s
    Setting up swapspace version 1, size = 15.6 GiB (16777211904 bytes)
    no label, UUID=48c2835b-4499-4534-aa49-0648e15bd5d9
    [sudo] password for masi: 
    swapon /media/masi/SamiWeek/tmp/swap_file_18.7.2016
    swapon: /media/masi/SamiWeek/tmp/swap_file_18.7.2016: insecure file owner 1000, 0 (root) suggested.
    swapon: /media/masi/SamiWeek/tmp/swap_file_18.7.2016: found swap signature: version 1d, page-size 4, same byte order
    swapon: /media/masi/SamiWeek/tmp/swap_file_18.7.2016: pagesize=4096, swapsize=16777216000, devsize=16777216000
    Swap enabled. Press enter to continue
    start_matlab_with_swap.sh: 11: read: arg count
    
  2. 运行客户端

    • 第一次启动 Matlab 时,命令历史记录在交换内存中消失(ticket #02075943),并出现错误读取你的命令历史记录时出现问题 - -。只需重新启动 Matlab,如果您有默认设置,问题就解决了。命令prefdir给出/home/masi/.matlab/R2016a默认位置(/home/{username}/.matlab/R2016a/home/masi/.matlab/R2016a/matlab.prf重新启动后文件存在,这里

    • ... [其他错误] ...

  3. 关闭 Matlab 并在终端中再次输入密码

    [sudo] password for masi: 
    swapoff /media/masi/SamiWeek/tmp/swap_file_18.7.2016
    [ bugs here! ]
    

打开:如何在此处应用错误捕获的更好错误处理?请参阅我的脚本以获取源代码中的示例。线程如果出现错误/警告,如何进行错误捕获和交换?

永久交换 = 将交换设置与正在运行的客户端分开

设置交换

# https://unix.stackexchange.com/q/297767/16920
masi@masi:~$ sudo fallocate -l 20G /mnt/.swapfile

masi@masi:~$ sudo mkswap /mnt/.swapfile 
Setting up swapspace version 1, size = 20 GiB (21474832384 bytes)
no label, UUID=45df9e48-1760-47e8-84d7-7a14f56bbd72

masi@masi:~$ sudo swapon /mnt/.swapfile
swapon: /mnt/.swapfile: insecure permissions 0644, 0600 suggested.

masi@masi:~$ sudo chmod 600 /mnt/.swapfile

masi@masi:~$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7925        1494         175         196        6255        5892
Swap:         28610           0       28610

将以下内容放在最后/etc/fstab进行永久更改

# https://unix.stackexchange.com/a/298212/16920
# https://unix.stackexchange.com/a/298543/16920

# If swap is on SSD, trim blocks each time at startup.
#/mnt/.swapfile  none    swap    defaults,discard      0        0

# If swap on External HDD, just use sw.
/media/masi/SamiWeek/.swapfile  none    swap    sw      0        0

系统:Linux Ubuntu 16.04 64 位
Linux 内核:4.6
Linux 内核选项:wl
Matlab:2016a
官方 Matlab 文档:解决“内存不足”错误
外置硬盘:Transcend 1 TB StoreJet 25M3审查, Transcend 2 TB StoreJet 25M3
外部硬盘文件系统:ext4
外部硬盘缓冲区:8 MB
相关主题:如何在 ubuntu 中增加 MATLAB 内存限制?(如何使用 mkswap、swapon 进行 MATLAB?)如何减少 Matlab 中的物理内存增加?如何解决 Matlab 中的内存不足错误?如何修复 Matlab 中 10800x10800 矩阵的内存不足错误?如何增加 Matlab r2012b 中的内存限制(连续和整体)?如何增加数组块并解决 Matlab 2009b 中的内存不足错误?如何解决 Matlab 中小变量的内存不足问题?Matlab 中“内存不足”。缓慢但永久的解决方案?

答案1

您无法为软件专门设置交换区。您可以做的是创建一个 shell 脚本来创建交换区,启动 MATLAB,并在 MATLAB 退出时删除交换区。

这是一个示例脚本,它在 /tmp 目录中创建一个 10Mb 的交换文件,挂载它,启动 R(我没有 matlab),等待 R 退出,卸载交换文件并将其删除。

请注意: - 您将收到警告,因为交换文件不属于 root。这是因为系统将使用它来处理任何软件,可能不是由您运行的,您可以在此文件中阅读...我让您修复它。 - 如果您 [ctrl]-[c] 脚本,或注销等,交换将保持挂载状态。我也让您修复它。

#!/usr/bin/env bash

SWAP_FILE=/tmp/my_swap_file
SIZE_MB=10
TO_RUN="R"

dd if=/dev/zero of=${SWAP_FILE} bs=1M count=${SIZE_MB}
mkswap ${SWAP_FILE}
chmod 0600 ${SWAP_FILE}
sudo swapon -v ${SWAP_FILE}
echo "Swap enabled. Press enter to continue"; read
${TO_RUN}
echo "I will remove the swap. Press enter to continue"; read
sudo swapoff -v ${SWAP_FILE}
rm -vf ${SWAP_FILE}

答案2

好的,你列出的清单相当多。让我在线回复

  1. 如何在此应用错误捕获的更好的错误处理?请参阅我的脚本以获取源代码中的示例。线程如何进行错误捕获并在出现错误/警告时进行交换?。

我一点也不喜欢这个脚本的概念。你有一个外部硬盘,并试图将其用作交换分区,这真是个坏主意。如果你真的打算定期这样做,那么请调整分区大小以放入合适的交换分区,添加交换文件,或者直接购买更大的内部磁盘。

  1. 如果矩阵大小超出交换大小,如何发出警告?

只需进行计算即可。如果您在程序启动之前知道矩阵的大小,则计算以 MiB 为单位的大小并将其与可用交换进行比较。

  1. 如何在 Matlab 中计算大型矩阵时显示进度条?

matlab 有 API 吗?我认为这里不适合讨论这个问题。即使你有 API,你也会通过交换阻塞 IO,所以它只是一个不稳定的进度条,实际上并不能反映现实。

  1. 如何在迭代(2)中终止繁忙的进程和/或 swapon -s/swapoff?

你不需要。仅仅因为你完成了计算并不意味着操作系统已经用完了你分配的资源。当它完成写入交换区时,它会释放。你已经消耗了太多内存,以至于许多应用程序无法获得所需的内存,所以它们也在使用交换区。只需将其打开并让操作系统完成它的工作。在执行下一次运行之前,请清除缓存。

echo 3 > /proc/sys/vm/drop_caches 

可能还有更多内容,我不是 Linux VM 专家。值得研究一下 SLAB/SLUB 分配器的工作原理以及如何针对您的大内存需求进行调整。您可能能够将 matlab MLOCK 放入内存中。这会强制操作系统为您保留内存,否则它根本无法启动,您还必须在完成后解锁它。我可以使用 C API 很好地做到这一点,但我不确定您如何在无法重新编译的进程之外做到这一点,这需要一些研究。

最后,这就是 EC2 的用途。看起来你需要的是 16G,m4.4xlarge 有 64G 内存,每小时 0.958 美元。这比一杯咖啡还便宜。使用 juju charm 或类似程序编写 matlab 安装脚本,并将整个过程转变为计算即服务。

16G 就是 16 GB 吗?

  • 是的,通常当我们省略后缀时,我们指的是以字节为单位的二进制数字。如果你想简洁的话,你可以写成 16GiB。

“我需要大于 100 GB 的矩阵。我不知道您是否可以使用 EC2 来实现。”

您是否也应该清除缓存echo 3 > /proc/sys/vm/drop_caches

  • 是的,总是这样做不会有什么坏处。请参阅 Linux 内核中的 Documentation/sysctl/vm.txt。

如何将 Matlab MLOCK 到内存中?

  • man mlock。虽然我引用的时候犯了个错误。这个调用确保你可以分配你想要的所有内存,并且不被换出,它永远不会使用虚拟内存。这不是你想要的。

我认为您可以将 C API 绑定到 Matlab。——如果进程出现任何故障,您是否知道如何关闭交换?

  • 我要坦白地说,以你提议的方式微观管理交换文件的概念是荒谬的。操作系统的工作是管理资源并以公平一致的方式分配资源。一旦你给它更多的资源,它就会按照它认为合适的方式使用它们。你无法告诉它何时完成并从它下面抽出资源,操作系统会告诉你何时完成。

当我向操作系统请求内存地址空间时,有时它并不总是成功,但这并不意味着我不能再试一次。matlab 无法弄清楚两次调用 malloc 是 matlab 的问题。

因此,为了实现您想要的更改,如果这 100G 空间是确实很贵然后您需要弄清楚如何告诉操作系统减少其内存占用(首先通过清除缓存),以便内存管理器不会觉得需要使用为其提供的额外交换空间。然后,您才能要求内存管理器释放交换文件。

增加内存和磁盘等东西很容易,但减少它们却困难得多。减少会迫使每个在该空间中分配资源的用户重新平衡。如果我说“我有一个 100TB 的存储阵列,但现在我只需要 60TB,为什么当我移除 40TB 的磁盘时阵列会停止工作?”那么,答案是显而易见的,对吧?

就我所见,以下是您的选择。

  1. 研究 matlab C API,看看是否可以更好地控制如何为这些海量工作集分配内存。

  2. 重构您的计算,使用子矩阵或其他稀疏数据表示来计算您现在拥有的内容。

  3. 使用大量的线性代数库用 C/C++ 编写自己的程序来执行计算并使用mallocmmap匿名分配所需的地址空间。

答案3

如果您在 HDD/SSD 上有交换部分,请使用zswap。该模块zram在 HDD/SSD 上没有交换部分,因此 Hakala 的答案不适用。请参阅主题zram vs zswap vs zcache 终极指南:何时使用哪一个解释。设置zswap如主题中所述如何在 Ubuntu 16.04 中成功激活 Zswap 以进行 Matlab 计算?

  • 将相应行替换为以下行/etc/default/grub

    # https://wiki.archlinux.org/index.php/Zswap
    GRUB_CMDLINE_LINUX_DEFAULT="quiet splash zswap.enabled=1 zswap.max_pool_percent=25 zswap.compressor=lzo"
    
  • 跑步sudo update-grub

答案4

我至少会测试压缩 RAM(zram 内核模块,自内核版本 3.14 起可用)的性能。

下列的archlinux wiki 说明

modprobe zram
echo lz4 > /sys/block/zram0/comp_algorithm
echo 4G > /sys/block/zram0/disksize
mkswap --label zram0 /dev/zram0
swapon --priority 100 /dev/zram0

我猜测压缩的 RAM 应该比磁盘 I/O 更快。

为了在重启后也保留更改,请输入启动时命令/etc/rc.local并运行sudo systemctl enable rc-local.service

相关内容