我有这段代码:
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import time
import numpy as np
for t in [np.uint8, np.int8]:
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%=245
t1=time.clock()
a[a<32]=0
a[a>224]=0
t2=time.clock()
print("%2.3f ms"%((t2-t1)*1000), a.dtype)
我得到这个输出:
3.162 ms uint8
0.329 ms int8
如果它在有符号数组上运行,为什么这个[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
最佳答案 为了确保每个人都知道时差的来源,我将代码分解为每个步骤:
整个代码
%%timeit
tmp = np.array(a, dtype=np.uint8, copy=True)
tmp[tmp < 30] = 0
tmp[tmp > 224] = 0
10 loops, best of 3: 21.6 ms per loop
%%timeit
tmp = np.array(a, dtype=np.int8, copy=True)
tmp[tmp < 30] = 0
tmp[tmp > 224] = 0
100 loops, best of 3: 10.4 ms per loop
所以是的,整个操作更快,但让我们看一下每个设置操作所花费的时间:
%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 loops, best of 3: 19.3 ms per loop
100 loops, best of 3: 17.6 ms per loop
因此对于int8,每个设置都需要相同的时间:
100 loops, best of 3: 6.75 ms per loop
100 loops, best of 3: 4.36 ms per loop
让我们看看如果我们只根据索引创建一个新视图会发生什么:
%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 loops, best of 3: 17.9 ms per loop
100 loops, best of 3: 16.2 ms per loop
对于int8:
100 loops, best of 3: 7.64 ms per loop
100 loops, best of 3: 4.3 ms per loop
还是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 loops, best of 3: 4.25 ms per loop
100 loops, best of 3: 2.58 ms per loop
对于int8:
100 loops, best of 3: 4.26 ms per loop
100 loops, best of 3: 4.08 ms per loop
简而言之:在创建布尔掩码时,dtype没有太大区别,但如果使用布尔掩码创建数据的新视图,使用int会更快.但这只是一种错觉,因为实际上numpy看到它访问第一个操作中的所有元素(因为235在get8中被转换为-21)而在第二个操作中没有元素.使用uint时,两个操作的掩码都包含True和False(混合).
简介:numpy可以并且确实优化获取和设置数组的所有/没有元素.
在你提到的评论中,对于uint v = [10,100]更快,但在我的计算机上使用与上面相同的设置它们两者大致相同:
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.