Feo*_*ran 12 python arrays performance numpy
考虑下面的一段代码,它生成一些(可能)巨大的多维数组并numpy.tensordot用它执行(无论我们在这里乘以相同或两个不同的数组,并不重要).
import time
import numpy
L, N = 6, 4
shape = (2*L)*[N,]
A = numpy.arange(numpy.prod(shape)).reshape(shape)
A = A % 256 - 128 # [-127,+127]
axes=(range(1,2*L,2), range(0,2*L,2))
def run(dtype, repeat=1):
A_ = A.astype(dtype)
t = time.time()
for i in range(repeat):
numpy.tensordot(A_, A_, axes)
t = time.time() - t
print(dtype, ' \t%8.2f sec\t%8.2f MB' %(t, A_.nbytes/1e6))
Run Code Online (Sandbox Code Playgroud)
现在我们可以比较不同数据类型的性能,例如:
run(numpy.float64)
run(numpy.int64)
Run Code Online (Sandbox Code Playgroud)
由于数组只包含小整数,我想通过使用来节省一些内存dtype=int8.但是,这会减慢矩阵乘法A LOT.
第一个,对我的用例来说是重要的一个.其他仅供参考.使用Numpy 1.13.1和Python 3.4.2
L, N = 6, 4; A.size = 4**12 = 16777216
<class 'numpy.float64'> 59.58 sec 134.22 MB
<class 'numpy.float32'> 44.19 sec 67.11 MB
<class 'numpy.int16'> 711.16 sec 33.55 MB
<class 'numpy.int8'> 647.40 sec 16.78 MB
Run Code Online (Sandbox Code Playgroud)
具有不同数据类型的相同数组.内存按预期减少.但为什么CPU时间差异很大?如果有什么我期望int比...更快float.
L, N = 1, 4**6; A.size = (4**6)**2 = 16777216
<class 'numpy.float64'> 57.95 sec 134.22 MB
<class 'numpy.float32'> 42.84 sec 67.11 MB
Run Code Online (Sandbox Code Playgroud)
形状似乎没有很大的影响.
L, N = 5, 4
<class 'numpy.float128'> 10.91 sec 16.78 MB
<class 'numpy.float64'> 0.98 sec 8.39 MB
<class 'numpy.float32'> 0.90 sec 4.19 MB
<class 'numpy.float16'> 9.80 sec 2.10 MB
<class 'numpy.int64'> 8.84 sec 8.39 MB
<class 'numpy.int32'> 5.55 sec 4.19 MB
<class 'numpy.int16'> 2.23 sec 2.10 MB
<class 'numpy.int8'> 1.82 sec 1.05 MB
Run Code Online (Sandbox Code Playgroud)
较小的值,但同样奇怪的趋势.
L,N = 2,4; A.size = 4**4 = 256; 重复= 1000000
<class 'numpy.float128'> 17.92 sec 4.10 KB
<class 'numpy.float64'> 14.20 sec 2.05 KB
<class 'numpy.float32'> 12.21 sec 1.02 KB
<class 'numpy.float16'> 41.72 sec 0.51 KB
<class 'numpy.int64'> 14.21 sec 2.05 KB
<class 'numpy.int32'> 14.26 sec 1.02 KB
<class 'numpy.int16'> 13.88 sec 0.51 KB
<class 'numpy.int8'> 13.03 sec 0.26 KB
Run Code Online (Sandbox Code Playgroud)
除了float16慢得多,这里的一切都很好.
为什么int8非常大的阵列要慢得多?有没有办法解决?对于大型阵列,节省内存变得越来越重要
很遗憾,
正如评论中正确强调的那样,幕后的“引擎”是 BLAS,并且它没有本机整数类型。这就是为什么 float64 或 32 会运行得更快(在C++ 类似问题的相关答案中进行了一些讨论)。
作为问题核心的旁注,探索加速问题同时限制内存消耗的方法是使用 Cython,您可以在其中直接运行 C 代码并在 Python 中返回结果。