今天我发现了一个函数,我找到了一个(至少对我而言)奇怪的瓶颈:创建一个带有mask=None
或mask=0
的蒙版数组来初始化一个全零的蒙版,但形状与data
非常慢:
>>> 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
或手动创建遮罩要快得多:
>>> %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
或0
比False
或np.zeros(data.shape)
的{{1}}参数慢近2000倍?鉴于function docs仅表示:
必须可转换为与数据形状相同的布尔数组。 True表示屏蔽(即无效)数据。
我在Windows 10上使用python 3.5,numpy 1.11.0
答案 0 :(得分: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
调整其大小。
答案 1 :(得分: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))
所以似乎数组的连接步骤是瓶颈。