用Python将numpy数组写入文件的有效方法
我处理的数据约为600万,写入文件需要花费大量时间。我如何改进它 以下是我尝试过的两种方法:用Python将numpy数组写入文件的有效方法,python,numpy,Python,Numpy,我处理的数据约为600万,写入文件需要花费大量时间。我如何改进它 以下是我尝试过的两种方法: import numpy as np import time test_data = np.random.rand(6000000,12) T1 = time.time() np.savetxt('test',test_data, fmt='%.4f', delimiter=' ' ) T2 = time.time() print "Time:",T2-T1,"Sec" file3=open('tes
import numpy as np
import time
test_data = np.random.rand(6000000,12)
T1 = time.time()
np.savetxt('test',test_data, fmt='%.4f', delimiter=' ' )
T2 = time.time()
print "Time:",T2-T1,"Sec"
file3=open('test2','w')
for i in range(6000000):
for j in range(12):
file3.write('%6.4f\t' % (test_data[i][j]))
file3.write('\n')
T3 = time.time()
print "Time:",T3-T2,"Sec"
时间:56.6293179989秒
时间:115.468323946秒
我正在处理至少100个这样的文件,总时间是很多,请帮助。另外,我没有使用.npy或压缩格式编写,因为我需要在matlab中阅读它们并进行进一步处理。使用pickle怎么样?我发现它更快
import numpy as np
import time
import pickle
test_data = np.random.rand(1000000,12)
T1 = time.time()
np.savetxt('testfile',test_data, fmt='%.4f', delimiter=' ' )
T2 = time.time()
print ("Time:",T2-T1,"Sec")
file3=open('testfile','w')
for i in range(test_data.shape[0]):
for j in range(test_data.shape[1]):
file3.write('%6.4f\t' % (test_data[i][j]))
file3.write('\n')
file3.close()
T3 = time.time()
print ("Time:",T3-T2,"Sec")
file3 = open('testfile','wb')
pickle.dump(test_data, file3)
file3.close()
T4 = time.time()
print ("Time:",T4-T3,"Sec")
# load data
file4 = open('testfile', 'rb')
obj = pickle.load(file4)
file4.close()
print(obj)
输出是
Time: 9.1367928981781 Sec
Time: 16.366491079330444 Sec
Time: 0.41736602783203125 Sec
用泡菜怎么样?我发现它更快
import numpy as np
import time
import pickle
test_data = np.random.rand(1000000,12)
T1 = time.time()
np.savetxt('testfile',test_data, fmt='%.4f', delimiter=' ' )
T2 = time.time()
print ("Time:",T2-T1,"Sec")
file3=open('testfile','w')
for i in range(test_data.shape[0]):
for j in range(test_data.shape[1]):
file3.write('%6.4f\t' % (test_data[i][j]))
file3.write('\n')
file3.close()
T3 = time.time()
print ("Time:",T3-T2,"Sec")
file3 = open('testfile','wb')
pickle.dump(test_data, file3)
file3.close()
T4 = time.time()
print ("Time:",T4-T3,"Sec")
# load data
file4 = open('testfile', 'rb')
obj = pickle.load(file4)
file4.close()
print(obj)
输出是
Time: 9.1367928981781 Sec
Time: 16.366491079330444 Sec
Time: 0.41736602783203125 Sec
几乎总是比savetxt
快得多。它只是转储原始字节,而不必将它们格式化为文本。它还可以编写更小的文件,这意味着更少的I/O。在加载时,您将获得同样的好处:更少的I/O,并且没有文本解析
下面的所有内容基本上都是save
优点的变体。如果你看最后的时间,它们都在一个数量级之内,但都比savetxt
快两个数量级。所以,您可能只对200:1的加速感到满意,而不在乎进一步调整。但是,如果您确实需要进一步优化,请继续阅读
使用
DEFLATE
压缩保存数组。这意味着您浪费了大量CPU,但节省了一些I/O。如果是速度慢的磁盘使您速度变慢,那就是一场胜利。请注意,对于较小的数组,恒定的开销可能会比压缩加速带来的帮助更大,如果使用随机数组,则几乎不可能进行压缩
savez_compressed
也是一种多数组存储。这在这里似乎是不必要的,但是如果你把一个巨大的数组分为,比如说,20个较小的数组,有时速度会明显加快。(尽管我不知道为什么。)代价是,如果您只是加载
将.npz
和堆栈
阵列重新组合在一起,您就不会获得连续存储,因此如果这很重要,您必须编写更复杂的代码
请注意,我下面的测试使用了一个随机数组,因此压缩只是浪费了开销。但是针对zero
或arange
进行测试也会产生相反的误导,因此……这是在真实数据上进行测试的东西
另外,我使用的是一台具有相当快的SSD的计算机,因此CPU和I/O之间的权衡可能不像运行在任何机器上那样不平衡
,或分配到stdlib中的阵列,通过直写缓存备份到磁盘。这不应该减少总的I/O时间,但这意味着I/O不会在最后一次发生,而是分散在整个计算中,这通常意味着它可以与繁重的CPU工作并行发生。因此,与其花50分钟计算然后10分钟节省,不如花55分钟计算和节省 这是一个很难以任何合理的方式测试的程序,实际上没有做任何计算,所以我没有麻烦
或者它的一个替代品,比如或。没有理由认为pickle应该比原始数组转储快,但有时它似乎比原始数组转储快 对于一个简单的连续数组,比如我测试中的数组,pickle只是一个与二进制转储完全相同字节的小包装器,因此它只是一个纯粹的开销
为了进行比较,以下是我如何测试每一个:
In [70]: test_data = np.random.rand(1000000,12)
In [71]: %timeit np.savetxt('testfile', test_data)
9.95 s ± 222 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [72]: os.stat('testfile').st_size
Out[74]: 300000000
注意这里使用了%timeit
。如果您没有使用IPython,请使用stdlib中的timeit
模块详细地执行相同的操作。使用time
进行测试有各种各样的问题(如timeit
文档中所述,但最大的问题是您只进行了一次测试。对于基于I/O的基准测试,这尤其糟糕
这是每一个结果,但是,上面给出的警告,你应该只考虑前两个有意义的。
:9.95s,300MBsavetxt
:45.8毫秒,96MB保存
:360ms,90MBsavez_compressed
:287ms,96MBpickle
savetxt
快得多。它只转储原始字节,而不必将其格式化为文本。它还写入更小的文件,这意味着更少的I/O。在加载时,您将获得同样的好处:更少的I/O,无需进行文本解析
下面的所有内容基本上都是save
的优点之外的变体。如果你看最后的时间,它们都在一个数量级范围内,但都比savetxt
快两个数量级。因此,你可能只会对200:1的加速感到满意,而不在乎尝试使用twea但是,如果您确实需要进一步优化,请继续阅读
使用
DEFLATE
压缩保存阵列。这意味着您浪费了大量CPU,但节省了一些I/O。如果磁盘速度较慢,这是一个胜利。请注意,对于较小的阵列,恒定的开销可能会比压缩加速带来的帮助更大,如果您有一个随机阵列,则几乎没有压缩这是可能的
savez_compressed
也是一种多数组保存。这在这里似乎没有必要,但如果你将一个巨大的数组分为(比如)20个较小的数组,有时速度会快得多。(尽管我不知道为什么。)代价是,如果您只是加载将.npz
和堆栈
数组重新组合在一起,就不会获得连续存储,因此如果这很重要,您必须编写更复杂的代码
请注意,我下面的测试使用了随机数组,因此压缩只是浪费了开销。但是针对zero
或arange
进行测试会产生相反的误导