我需要从Python脚本中的文件(到Python列表)中加载(反序列化)预先计算的整数列表。列表很大(高达数百万项),只要加载速度最快,我就可以选择存储它的格式。
哪种方法最快,为什么?
import
,该文件只包含分配给变量的列表cPickle
的{{1}} load
?)此外,如何可靠地对这些事情进行基准测试?
附录:很难对此进行测量很困难,因为numpy
已缓存,因此无法在测试中多次执行。第一次使用pickle加载也会因为操作系统的页面预先缓存而变得更快。使用import
加载100万个数字第一次运行需要1.1秒,后续执行脚本需要0.2秒。
直觉我觉得cPickle
应该更快,但我会欣赏数字(我认为这是一个非常难以衡量的挑战)。
是的,对我来说这很重要。
由于
答案 0 :(得分:7)
如果您确实需要列表中的内容,我猜cPickle将是最快的。
如果您可以使用内置序列类型array,我会在四分之一秒内为100万个整数计时:
from array import array
from datetime import datetime
def WriteInts(theArray,filename):
f = file(filename,"wb")
theArray.tofile(f)
f.close()
def ReadInts(filename):
d = datetime.utcnow()
theArray = array('i')
f = file(filename,"rb")
try:
theArray.fromfile(f,1000000000)
except EOFError:
pass
print "Read %d ints in %s" % (len(theArray),datetime.utcnow() - d)
return theArray
if __name__ == "__main__":
a = array('i')
a.extend(range(0,1000000))
filename = "a_million_ints.dat"
WriteInts(a,filename)
r = ReadInts(filename)
print "The 5th element is %d" % (r[4])
答案 1 :(得分:3)
有关基准测试,请参阅Python标准库中的timeit模块。要了解最快的方法,请实施您能想到的所有方法并使用timeit进行测量。
随机思考:根据您正在做的事情,您可能会发现以 .newsrc 文件中使用的样式存储“整数组”的速度最快:
1, 3-1024, 11000-1200000
如果你需要检查那个集合中是否有东西,那么加载和匹配这样的表示应该是最快的方法。这假设您的整数集合相当密集,具有相邻值的长连续序列。
答案 2 :(得分:2)
“如何可靠地对这些事情进行基准测试?”
我不明白这个问题。
您编写了许多小函数来以各种形式创建和保存列表。
您编写了一些小函数来以各种形式加载列表。
你写了一个小计时器函数来获取开始时间,执行加载程序几十次(得到一个足够长的稳定平均值,以至于OS调度噪声不会影响你的测量)。
您可以在一份小报告中总结您的数据。
这有什么不可靠的?
以下是一些不相关的问题,展示了如何衡量和比较绩效。
答案 3 :(得分:2)
为了帮助您计时,Python库提供了timeit
模块:
该模块提供了一种简单的方法来计算一小段Python代码。它既有命令行,也有可调用的接口。它避免了许多用于测量执行时间的常见陷阱。
比较使用hasattr()
与try/except
测试缺失和当前对象属性的成本的示例(来自手册):
% timeit.py 'try:' ' str.__nonzero__' 'except AttributeError:' ' pass'
100000 loops, best of 3: 15.7 usec per loop
% timeit.py 'if hasattr(str, "__nonzero__"): pass'
100000 loops, best of 3: 4.26 usec per loop
% timeit.py 'try:' ' int.__nonzero__' 'except AttributeError:' ' pass'
1000000 loops, best of 3: 1.43 usec per loop
% timeit.py 'if hasattr(int, "__nonzero__"): pass'
100000 loops, best of 3: 2.23 usec per loop
答案 4 :(得分:2)
您是否需要始终加载整个文件?如果没有,upack_from()可能是最佳解决方案。假设你有1000000个整数,但是你只想加载50000到50099之间的整数,你可以这样做:
import struct
intSize = struct.calcsize('i') #this value would be constant for a given arch
intFile = open('/your/file.of.integers')
intTuple5K100 = struct.unpack_from('i'*100,intFile,50000*intSize)
答案 5 :(得分:1)
cPickle将是最快的,因为它以二进制保存,并且不需要解析真正的python代码。
其他优点是它更安全(因为它不执行命令)并且你没有正确设置$PYTHONPATH
的问题。