在预分配大量内存(例如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
这与虚拟内存无关。 这是一个众所周知的问题吗?
答案 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秒。因此,分配不占用所有(或甚至很多时间)并且数据分配到阵列也不需要花费太多时间,但是阵列的分配状态确实会影响系统调用所需的时间执行。非常奇怪。