np.uint8和np.int8的执行时间不同

时间:2016-03-01 17:03:24

标签: python python-3.x numpy

我有这段代码:

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}}

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跳过这个。