-->

NumPy的点积很慢使用int(Numpy dot product very slow using

2019-06-26 20:34发布

对不起,这么多的问题。 我在英特尔酷睿2双核上运行的Mac OSX 10.6。 我正在为我的研究提供一定的基准,我遇到了那个令我感到困惑另一件事。

如果我运行

python -mtimeit -s 'import numpy as np; a = np.random.randn(1e3,1e3)' 'np.dot(a,a)'

我得到以下输出: 10 loops, best of 3: 142 msec per loop

但是,如果我跑

python -mtimeit -s 'import numpy as np; a = np.random.randint(10,size=1e6).reshape(1e3,1e3)' 'np.dot(a,a)'

我得到以下输出: 10 loops, best of 3: 7.57 sec per loop

然后我跑

python -mtimeit -s 'import numpy as np; a = np.random.randn(1e3,1e3)' 'a*a' python -mtimeit -s 'import numpy as np; a = np.random.randn(1e3,1e3)' 'a*a'然后

python -mtimeit -s 'import numpy as np; a = np.random.randint(10,size=1e6).reshape(1e3,1e3)' 'a*a'

无论在跑每循环约7.6毫秒,所以它不是乘法。 添加了类似的速度一样,所以这些都不应该成为影响点积,对不对? 那么,为什么在50倍慢计算使用int比使用浮动点产品?

Answer 1:

很有趣,我很好奇,想看看它是如何实现的,所以我做:

>>> import inspect
>>> import numpy as np
>>> inspect.getmodule(np.dot)
<module 'numpy.core._dotblas' from '/Library/Python/2.6/site-packages/numpy-1.6.1-py2.6-macosx-10.6-universal.egg/numpy/core/_dotblas.so'>
>>> 

所以看起来它使用类似BLAS库。

所以:

>>> help(np.core._dotblas)

从中我发现这一点:

当NumPy的与加速BLAS像ATLAS建成,这些功能将被替换,以充分利用更快的实现。 更快的实现只影响FLOAT32,float64,complex64和complex128阵列。 此外,BLAS API仅包括矩阵矩阵,矩阵矢量和矢量矢量乘积。 具有较大维度阵列产品使用内置的功能,而不是加速。

所以它看起来像ATLAS微调某些功能,但其只适用于特定的数据类型,非常有趣。

所以是它看起来我会更经常地使用花车...



Answer 2:

使用INT VS浮点数据类型将导致执行不同的代码路径:

浮法堆栈跟踪看起来是这样的:

(gdb) backtr
#0  0x007865a0 in dgemm_ () from /usr/lib/libblas.so.3gf
#1  0x007559d5 in cblas_dgemm () from /usr/lib/libblas.so.3gf
#2  0x00744108 in dotblas_matrixproduct (__NPY_UNUSED_TAGGEDdummy=0x0, args=(<numpy.ndarray at remote 0x85d9090>, <numpy.ndarray at remote 0x85d9090>), 
kwargs=0x0) at numpy/core/blasdot/_dotblas.c:798
#3  0x08088ba1 in PyEval_EvalFrameEx ()
...

..while堆栈跟踪INT看起来是这样的:

(gdb) backtr
#0  LONG_dot (ip1=0xb700a280 "\t", is1=4, ip2=0xb737dc64 "\a", is2=4000, op=0xb6496fc4 "", n=1000, __NPY_UNUSED_TAGGEDignore=0x85fa960)
at numpy/core/src/multiarray/arraytypes.c.src:3076
#1  0x00659d9d in PyArray_MatrixProduct2 (op1=<numpy.ndarray at remote 0x85dd628>, op2=<numpy.ndarray at remote 0x85dd628>, out=0x0)
at numpy/core/src/multiarray/multiarraymodule.c:847
#2  0x00742b93 in dotblas_matrixproduct (__NPY_UNUSED_TAGGEDdummy=0x0, args=(<numpy.ndarray at remote 0x85dd628>, <numpy.ndarray at remote 0x85dd628>), 
kwargs=0x0) at numpy/core/blasdot/_dotblas.c:254
#3  0x08088ba1 in PyEval_EvalFrameEx ()
...

两个调用导致dotblas_matrixproduct,但现在看来,浮动呼叫保持在BLAS库(可能访问某些精心优化的代码),而INT呼叫被踢回给numpy的的PyArray_MatrixProduct2。

因此,这可以是一个错误或BLAS只是不支持matrixproduct整数类型(这似乎相当不可能的)。

下面是一个简单和廉价的解决方法:

af = a.astype(float)
np.dot(af, af).astype(int)


文章来源: Numpy dot product very slow using ints