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

Léo*_* 준영 17 swap ram matlab 16.04

情况:修复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
    
    Run Code Online (Sandbox Code Playgroud)
  • Matlab 的配置

    % /sf/answers/2517972831/
    com.mathworks.services.Prefs.setIntegerPref('JavaMemHeapMax', 2048); % MB
    
    % TODO cannot find ways how to put Matlab use /dev/sda3
    
    Run Code Online (Sandbox Code Playgroud)
  • 所以你看到我的 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

# /sf/answers/4886591/
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}
Run Code Online (Sandbox Code Playgroud)

使用 Transcend 25M3 1 TB 的迭代 1,几乎没有使用 berofe where 文件系统 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
    
    Run Code Online (Sandbox Code Playgroud)
  2. 运行客户端

    • 命令历史在交换内存中的 Matlab 的第一次启动中消失了(票号 #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! ]
    
    Run Code Online (Sandbox Code Playgroud)

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

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

设置交换

# 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
Run Code Online (Sandbox Code Playgroud)

将以下内容放在/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
Run Code Online (Sandbox Code Playgroud)

系统: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 for MATLAB?)如何减少 Matlab 中物理内存的增加?,如何解决 Matlab 中的内存不足错误?,如何修复 10800x10800 矩阵的 Matlab 内存不足错误?,如何在 Matlab r2012b 中增加内存限制(连续和整体)?,如何在 Matlab 2009b 中增加数组块并解决内存不足错误?,如何解决 Matlab 中小变量的内存不足问题?, Matlab 中的“内存不足”。一个缓慢但永久的解决方案?

Mic*_*man 12

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

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

请注意: - 您将收到警告,因为交换文件不归 root 所有。那是因为系统将使用 if 用于任何软件,可能不是您运行的,您可以阅读此文件...我让您修复它。- 如果您 [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}
Run Code Online (Sandbox Code Playgroud)


ppe*_*aki 2

好的,你那里有一份相当多的清单。让我内联回复

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

我根本不喜欢这个脚本的概念。您尝试将外部硬盘用作交换只是一个坏主意。如果您确实打算定期执行此操作,请调整分区大小以放入适当的交换分区,添加交换文件,或者只是购买更大的内部磁盘。

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

只需做一下数学计算即可。如果您在程序开始之前知道矩阵的大小,则计算 MiB 的大小并将其与可用交换进行比较。

  1. 如何在Matlab中计算巨大矩阵时有进度条?

matlab有API吧?我认为这不是解决该问题的正确论坛。即使您有 API,您也会通过交换阻塞 IO,因此它只是一个不稳定的进度条,实际上并不能反映现实。

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

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

echo 3 > /proc/sys/vm/drop_caches 
Run Code Online (Sandbox Code Playgroud)

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

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

16G就是16GB吗?

  • 是的,通常当我们省略后缀时,我们指的是以字节为单位的 base2 数字。如果你想简洁的话可以写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匿名来分配您需要的地址空间。