2016-05-26 3 views
5

今日、私は関数をプロファイリングして、少なくとも私に奇妙なボトルネックが見つかりました:mask=Noneまたはmask=0でマスクされた配列を作成してマスクを初期化しますmask = numまたはmask = 0でマスクされたnumpy配列を作成しているのはなぜですか?

>>> %timeit ma_array = np.ma.array(data, mask=False, copy=False) 
1000 loops, best of 3: 438 µs per loop 

>>> %timeit ma_array = np.ma.array(data, mask=np.zeros(data.shape, dtype=bool), copy=False) 
1000 loops, best of 3: 453 µs per loop 

なぜNoneまたはを与えている:はるかに速く

>>> import numpy as np 
>>> data = np.ones((100, 100, 100)) 

>>> %timeit ma_array = np.ma.array(data, mask=None, copy=False) 
1 loop, best of 3: 803 ms per loop 

>>> %timeit ma_array = np.ma.array(data, mask=0, copy=False) 
1 loop, best of 3: 807 ms per loop 

mask=Falseを用いて、または手でマスクを作成する一方れる:すべてゼロしかしdata同じ形状と非常に遅いです0約2000倍遅いFalseまたはnp.zeros(data.shape)としてmaskパラメータ? function docsには、次のように書かれています。

データと同じ形のブール値の配列に変換可能である必要があります。 Trueはマスクされた(つまり無効な)データを示します。

私のpython 3.5を使用して、Windowsの10のnumpyの1.11.0

+0

numpyコードをまだ掘り下げましたか? –

答えて

4

mask=Falseは特殊ケースに入れNumPy 1.11.0 source codeである:

if mask is True and mdtype == MaskType: 
    mask = np.ones(_data.shape, dtype=mdtype) 
elif mask is False and mdtype == MaskType: 
    mask = np.zeros(_data.shape, dtype=mdtype) 

mask=0またはmask=None 0-を作り、低速パスを取りますそれをサイズ変更するためにnp.resizeを通過する。

+0

'' resize'は 'a = concatenate((a、)* n_copies)'を実行します。 – hpaulj

1

@ user2357112は説明があると思います。

In [14]: q.run('q.np.ma.array(q.data, mask=None, copy=False)') 
     49 function calls in 0.161 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     3 0.000 0.000 0.000 0.000 :0(array) 
     1 0.154 0.154 0.154 0.154 :0(concatenate) 
     1 0.000 0.000 0.161 0.161 :0(exec) 
     11 0.000 0.000 0.000 0.000 :0(getattr) 
     1 0.000 0.000 0.000 0.000 :0(hasattr) 
     7 0.000 0.000 0.000 0.000 :0(isinstance) 
     1 0.000 0.000 0.000 0.000 :0(len) 
     1 0.000 0.000 0.000 0.000 :0(ravel) 
     1 0.000 0.000 0.000 0.000 :0(reduce) 
     1 0.000 0.000 0.000 0.000 :0(reshape) 
     1 0.000 0.000 0.000 0.000 :0(setprofile) 
     5 0.000 0.000 0.000 0.000 :0(update) 
     1 0.000 0.000 0.161 0.161 <string>:1(<module>) 
     1 0.000 0.000 0.161 0.161 core.py:2704(__new__) 
     1 0.000 0.000 0.000 0.000 core.py:2838(_update_from) 
     1 0.000 0.000 0.000 0.000 core.py:2864(__array_finalize__) 
     5 0.000 0.000 0.000 0.000 core.py:3264(__setattr__) 
     1 0.000 0.000 0.161 0.161 core.py:6119(array) 
     1 0.007 0.007 0.161 0.161 fromnumeric.py:1097(resize) 
     1 0.000 0.000 0.000 0.000 fromnumeric.py:128(reshape) 
     1 0.000 0.000 0.000 0.000 fromnumeric.py:1383(ravel) 
     1 0.000 0.000 0.000 0.000 numeric.py:484(asanyarray) 
     0 0.000    0.000   profile:0(profiler) 
     1 0.000 0.000 0.161 0.161 profile:0(q.np.ma.array(q.data, mask=None, copy=False)) 

In [15]: q.run('q.np.ma.array(q.data, mask=False, copy=False)') 
     37 function calls in 0.000 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.000 0.000 :0(array) 
     1 0.000 0.000 0.000 0.000 :0(exec) 
     11 0.000 0.000 0.000 0.000 :0(getattr) 
     1 0.000 0.000 0.000 0.000 :0(hasattr) 
     5 0.000 0.000 0.000 0.000 :0(isinstance) 
     1 0.000 0.000 0.000 0.000 :0(setprofile) 
     5 0.000 0.000 0.000 0.000 :0(update) 
     1 0.000 0.000 0.000 0.000 :0(zeros) 
     1 0.000 0.000 0.000 0.000 <string>:1(<module>) 
     1 0.000 0.000 0.000 0.000 core.py:2704(__new__) 
     1 0.000 0.000 0.000 0.000 core.py:2838(_update_from) 
     1 0.000 0.000 0.000 0.000 core.py:2864(__array_finalize__) 
     5 0.000 0.000 0.000 0.000 core.py:3264(__setattr__) 
     1 0.000 0.000 0.000 0.000 core.py:6119(array) 
     0 0.000    0.000   profile:0(profiler) 
     1 0.000 0.000 0.000 0.000 profile:0(q.np.ma.array(q.data, mask=False, copy=False)) 

は、だから、配列の連結ステップがボトルネックになっているようだ:私は両方のケースをプロファイリング、ここでの結果です。

関連する問題