16

たくさんの質問をしてすみません。Intel Core2DuoでMacOSX10.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.randint(10,size=1e6).reshape(1e3,1e3)' 'a*a'

どちらもループあたり約7.6ミリ秒で実行されたため、乗算ではありません。追加の速度も同様だったので、どちらも内積に影響を与えないはずですよね?では、floatを使用するよりもintを使用してドット積を計算する方が50倍以上遅いのはなぜですか?

4

2 に答える 2

15

非常に興味深いので、それがどのように実装されているかを知りたいと思ったので、次のようにしました。

>>> 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がATLASのような高速化されたBLASで構築されている場合、これらの関数はより高速な実装を利用するために置き換えられます。より高速な実装は、float32、float64、complex64、およびcomplex128配列にのみ影響します。さらに、BLAS APIには、行列-行列、行列-ベクトル、およびベクトル-ベクトルの積のみが含まれます。より大きな次元の配列の製品は、組み込み関数を使用し、高速化されません。

したがって、ATLASは特定の機能を微調整しているように見えますが、特定のデータ型にのみ適用可能であり、非常に興味深いものです。

そうそう、私はもっと頻繁にフロートを使うように見えます...

于 2012-08-08T02:00:59.113 に答える
7

intとfloatのデータ型を使用すると、さまざまなコードパスが実行されます。

floatのスタックトレースは次のようになります。

(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 ()
...

..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につながりますが、float呼び出しはBLASライブラリにとどまり(おそらく適切に最適化されたコードにアクセスします)、int呼び出しはnumpyのPyArray_MatrixProduct2にキックバックされます。

したがって、これはバグであるか、BLASがmatrixproductの整数型をサポートしていないだけです(これはかなりありそうもないようです)。

簡単で安価な回避策は次のとおりです。

af = a.astype(float)
np.dot(af, af).astype(int)
于 2012-08-08T01:55:31.743 に答える