性能问题:大numpy数组和系统调用

时间:2012-05-14 14:49:24

标签: python performance memory numpy

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

test.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

这与虚拟内存无关。 这是一个众所周知的问题吗?

2 个答案:

答案 0 :(得分:5)

在分配了大量NumPy数组之后,您似乎已将问题缩小到os.system()

在幕后,system()使用fork()。尽管fork()应该非常便宜(由于它使用了copy-on-write),但事实并非如此简单。

特别是,Linux的fork()存在大问题需要更长时间才能处理更大的进程。例如,见:

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

如果你无法摆脱那些system()电话,我会提出两种研究途径:

  • 考虑启用大页面。
  • 考虑在启动时产生辅助进程的可能性,其工作是调用必要的system()命令。

答案 1 :(得分:4)

如果您不使用os.system来电,会怎样?

对我来说:

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

每次没有os.system,它大约增加一个magnitide。所以,我会说你的问题出在系统调用中,而不是numpy的性能(这是通过做同样的测试来确认的,除了这次评论代码的numpy部分)。此时,问题变成“为什么重复系统调用会慢(呃)?” ......不幸的是,我没有答案。

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

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

问题似乎不仅仅是os.system - subprocess.Popen遭受同样的弊端......(尽管subprocess可能只会在os.system下面调用{{1}}引擎盖,我其实不知道......)

修改

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