我有这段代码:
3.162 ms uint8
0.329 ms int8
我得到了这个输出:
a[a<32]=0
如果它在签名数组上运行,为什么这个for t in [np.int8, np.uint8]:
a=np.empty([480, 640], t)
v=[10, 245]
for y in range(480):
for x in range(640):
a[y, x]=v[x&1] # 50%=10, 50%=235
t1=time.process_time()
for l in range(1000):
b=1*a # deep copy
b[b<32]=0
b[b>224]=0
t2=time.process_time()
print("%5.4f ms"%((t2-t1)*1000), a.dtype)
要快十倍?
有没有办法在无符号数组上加速?
是的......它与更多样本相同:
328.0701 ms int8
3081.5300 ms uint8
结果如下:
{{1}}
答案 0 :(得分:1)
为了确保每个人都知道时差的来源,我将代码分解为每个步骤:
整个代码
%%timeit
tmp = np.array(a, dtype=np.uint8, copy=True)
tmp[tmp < 30] = 0
tmp[tmp > 224] = 0
10个循环,最佳3:每循环21.6 ms
%%timeit
tmp = np.array(a, dtype=np.int8, copy=True)
tmp[tmp < 30] = 0
tmp[tmp > 224] = 0
100个循环,最佳3:每循环10.4 ms
所以是的,整个操作更快,但让我们看看每次设置操作所用的时间:
%timeit tmp = np.array(a, dtype=np.uint8, copy=True); tmp[tmp < 30] = 0
tmp = np.array(a, dtype=np.uint8, copy=True)
tmp[tmp < 30] = 0
%timeit tmp2 = np.array(tmp, copy=True); tmp2[tmp2 > 224] = 0
100个循环,最佳3:每循环19.3毫秒
100个循环,最佳3:每循环17.6毫秒
因此,对于int8
:
100个循环,最佳3:6.75毫秒/循环
100个循环,最佳3:每循环4.36 ms
如果我们只根据索引创建新视图,请看看会发生什么:
%timeit tmp = np.array(a, dtype=np.uint8, copy=True); _ = tmp[tmp < 30]
tmp = np.array(a, dtype=np.uint8, copy=True)
tmp[tmp < 30] = 0
%timeit tmp2 = np.array(tmp, copy=True); _ = tmp2[tmp2 > 224]
100个循环,最佳3:每循环17.9 ms
100个循环,最佳3:每循环16.2 ms
和int8
:
100个循环,最好为3:每循环7.64毫秒
100个循环,最佳3:每循环4.3毫秒
仍然int
更快。那么创建布尔掩码:
%timeit tmp = np.array(a, dtype=np.uint8, copy=True); _ = tmp < 30
tmp = np.array(a, dtype=np.uint8, copy=True)
tmp[tmp < 30] = 0
%timeit tmp2 = np.array(tmp, copy=True); _ = tmp2 > 224
100个循环,最佳3:每循环4.25毫秒
100个循环,最佳3:每循环2.58 ms
和int8
:
100个循环,最佳3:每循环4.26 ms
100个循环,最佳3:每循环4.08毫秒
长话短说:在创建布尔蒙版时,dtype没有太大的区别,但是如果使用布尔掩码创建数据的新视图,int
的速度要快得多。但这仅仅是一种错觉,因为实际上numpy看到它在第一次操作中访问所有元素(因为235在int8
中被转换为-21)和<第二个操作中的strong> no 元素。使用uint
两个操作的掩码包含True和False(混合)。
总结:numpy可以并且确实优化获取和设置数组的所有/没有元素。
在你提到的评论中v=[10,100]
使用uint
的速度更快,但在我的电脑上使用与上面相同的设置,它们两者大致相同:
uint: 10 loops, best of 3: 21.7 ms per loop
int: 10 loops, best of 3: 23.2 ms per loop
这是因为现在第一个操作有一个混合布尔掩码,numpy不能像设置all / no元素那样优化它。但是第二个操作有一个只有False
的布尔掩码,所以numpy为uint和int跳过这个。