3

在预分配大量内存(例如 numpy 数组)后使用系统调用时会出现性能问题。这个问题随着内存量的增加而增加。

测试.py:

import os
import sys
import time
import numpy

start = time.clock()
test = int(sys.argv[1])
a = numpy.zeros((test,500,500))
for i in range(test) :
    os.system("echo true > /dev/null")
elapsed = (time.clock() - start)
print(elapsed)

每次迭代时间显着增加:

edouard@thorin:~/now3/code$ python test.py 100
0.64
edouard@thorin:~/now3/code$ python test.py 200
2.09
edouard@thorin:~/now3/code$ python test.py 400
14.26

这不应该与虚拟内存有关。这是一个已知问题吗?

4

2 回答 2

5

os.system()在分配了一个大型 NumPy 数组后,您似乎已将问题缩小到需要更长时间。

在幕后,system()使用fork(). 尽管fork()应该非常便宜(由于它使用了写时复制),但事实证明事情并不那么简单。

特别是,已知的问题是 Linuxfork()需要更长的时间来处理更大的进程。参见,例如:

这两份文件都相当旧,所以我不确定最先进的技术是什么。但是,证据表明您遇到了此类问题。

如果您无法摆脱这些system()电话,我会建议两种研究途径:

  • 研究启用大页面。
  • 考虑在启动时产生一个辅助进程的可能性,它的工作是调用必要的system()命令。
于 2012-05-14T16:02:27.913 回答
4

如果您不使用os.system通话会发生什么?

为了我:

python test.py 10   # 0.14
python test.py 100  # 1.18
python test.py 1000 # 11.77

在没有 的情况下,它每次大约增长一个数量级os.system。所以,我想说你的问题出在系统调用上,而不是 numpy 的性能上(这通过进行相同的测试得到证实,除了这次注释掉代码的 numpy 部分)。此时,问题变成了“为什么重复系统调用很慢(呃)?” ......不幸的是,我没有答案。

有趣的是,如果我在 bash 中执行此操作,则没有问题(它几乎立即返回)...

time for i in `seq 1 1000`; do echo true > /dev/null; done

似乎问题不只是os.system——subprocess.Popen遭受同样的恶意......(虽然,subprocess可能只是os.system在幕后打电话,我实际上不知道......)

编辑

这越来越好。在我之前的测试中,我离开了 numpy 数组的分配......如果你也删除了 numpy 数组的分配,测试进行得相对较快。但是,数组 (1000,800,800) 的分配只需要大约 1 秒。因此,分配不会占用所有(甚至大部分时间),并且将数据分配给数组也不会花费太多时间,但是数组的分配状态确实会影响系统调用所需的时间执行。很奇怪。

于 2012-05-14T14:54:54.777 回答