bza*_*row 5 memory linux performance swap
我并行运行了一堆 CPU 饥渴的进程;它们通常每个使用几 GB 的内存。他们有时也会分配大量内存(比如 150-250GB)。通常最多只有一个进程这样做,因此它们适合可用的 RAM(我的机器上为 384GB)。然而,有时会发生更多的人同时分配这么大的数量,并且(显然)由于交换而一切都变慢了。
在这种情况下,我会停止除一个内存占用进程之外的所有进程,以使其有效计算。但是换入一个停止的进程需要很长时间,因为这意味着以随机访问模式从磁盘加载数十 GB。因此问题是:如何强制单个进程从交换中顺序加载整个核心?
到目前为止,我只找到了一个 swappiness 内核提示,它(在 cgroups 的帮助下)可以防止进程进行更多的交换,但对去交换的性能没有帮助。关闭所有交换显然是不可能的,因为其他停止的进程必须占用那里的空间。
构建我自己的迷你调度程序也不是一种选择 - 进程是 python 中的各种小脚本/程序,内存峰值通常发生在库调用中,所以我无法预测峰值何时会出现。
澄清一下:我不考虑购买 TB 级的 RAM,在这种规模下它太贵了。将交换放在 SSD/SSD 阵列上只会有一点帮助(测量),因此它也不是我正在寻找的解决方案。
(部分自答):
看起来,如果没有内核黑客攻击,真正的顺序交换读取(仅属于单个进程的页面)几乎是不可能的:我测量过swapoff -a,它肯定没有顺序读取交换。如果这样的优化很容易实现,那么更快地阅读它是合乎逻辑的。
目前我最好的方法是/proc/[pid]/mem使用下面的脚本(必须以 root 身份运行)通过伪文件读取整个进程内存:
#!/usr/bin/python2
import re
import sys
pid=str(sys.argv[1]) # process pid given by the first arg
print(pid) # just to aviod mistakes
CHUNKSIZE=10485760 # single read() invocation block size
total=0
maps_file = open("/proc/"+pid+"/maps", 'r')
mem_file = open("/proc/"+pid+"/mem", 'r', 0)
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
togo = end-start # number of bytes to read
while togo > CHUNKSIZE: # read sequential memory from region one block at the moment
mem_file.read(CHUNKSIZE)
togo -= CHUNKSIZE
total += CHUNKSIZE
print(total/1048576) # be verbose, print megabytes read so far
mem_file.read(togo) # read remaining region contents
total+=togo # dump contents to standard output
print(total/1048576) # be verbose...
maps_file.close()
mem_file.close()
Run Code Online (Sandbox Code Playgroud)
它碰巧在内存的最后一个字节失败,但通常具有与swapoff给定进程相同的性能并仅加载给定进程。脚本是此答案的修改后的片段。
| 归档时间: |
|
| 查看次数: |
676 次 |
| 最近记录: |