【问题标题】:How is the Numpy "fill" method implemented?Numpy“填充”方法是如何实现的?
【发布时间】:2016-11-20 23:23:18
【问题描述】:

您会看到使用 Core Python 方法和 Numpy 方法创建了两个相等的数组:

from time import time
import numpy as np

a = [3] * 100000
b = np.array(a)

问题是,Numpy 在填充过程中怎么可能比 Core Python 方法快:

填充:

st = time()
for i in range(len(a)):
    a[i] = 0
et = time()
print "Core Python need %f seconds" % (et-st)

st = time()
b.fill(0)
et = time()
print "Numpy need %f seconds" %  (et-st) 

结果:

Core Python need 0.014000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.014000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.001000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.001000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.014000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.013000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.014000 seconds
Numpy need 0.000000 seconds
>>> ================================ RESTART ================================
>>> 
Core Python need 0.014000 seconds
Numpy need 0.000000 seconds
>>> 

【问题讨论】:

  • 有趣的问题。也许数组和列表不是一回事? +Core Python 必须通过循环。 Fill 可能会以更有效的方式做到这一点,
  • 数组是连续的内存块,列表不是。用特定值填充连续的内存块很容易,尤其是0,用相同的值填充列表要“更难”。
  • @Holt 你的意思是:在 python 中,一个 100,000 个元素的列表可能在不同的内存位置使用不同的小块,而对于数组来说它是一个大块?有什么规范吗?
  • 执行a[:] = [0]*len(a) 可能比显式的for 循环更快。
  • @EbraHim 如果您熟悉 C/C++ 等语言,您可以将 numpy 数组视为“ints 的数组”,将 python 列表视为“指向int 的指针数组” .

标签: python python-2.7 numpy


【解决方案1】:

如果包含将a 转换为 numpy 数组的时间,那么核心 python 方法所花费的时间大致相同。

In [14]: %%timeit
   ....: a = [3] * 100000
   ....: for i in range(len(a)):
   ....:     a[i] = 0
   ....:
100 loops, best of 3: 9.94 ms per loop

In [15]: %%timeit
   ....: a = [3] * 100000
   ....: b = np.array(a)
   ....: b.fill(0)
   ....:
100 loops, best of 3: 9.47 ms per loop

【讨论】:

  • 我同意在执行 %%timeit 之前初始化 a 和 b 是个好主意。但是-您应该将 python-loop 与 np.fill() 函数进行比较-此比较的结果是:python-loop 比 np.fill() 操作慢 1000 倍
【解决方案2】:

您的 2 个“数组”可能具有相同的值,但它们的存储方式不同

a = [3] * 100000
b = np.array(a)

a,作为一个列表,由 100000 个指向数字 3 的指针组成(存储在内存中的其他位置)。 a[i]=0 将这些指针之一更改为0 的位置。您的循环以解释的 Python 速度更改每个指针。

大部分时间都花在循环机制上:

In [139]: %%timeit a=[3]*100000
     ...: for i in range(len(a)):a[i]=0    
100 loops, best of 3: 13.4 ms per loop

In [140]: %%timeit a=[3]*100000
     ...: for i in range(len(a)):pass 
100 loops, best of 3: 5.86 ms per loop

b 是一个新结构,一个 numpy 数组。从列表中创建它需要一些时间:

In [142]: %timeit b=np.array(a)
100 loops, best of 3: 15.8 ms per loop

但是一旦创建,numpy 可以以快速的编译代码速度执行许多任务。 b.fill 就是其中之一。

In [144]: %%timeit b=np.array(a)
     ...: b.fill(0)
10000 loops, best of 3: 74 µs per loop

由于代码已编译,您无法轻易看到 fill 是如何完成的。

b 是一个具有形状和步幅等属性的对象,以及一个数据缓冲区。在这种情况下,缓冲区以 c 数组开始,其中包含许多 3s(不是指向 3 的指针)。 numpy fill(0) 执行快速的c 操作,将0 写入每个字节。

所以有两个关键区别

  • 存储(点列表 v 值列表)
  • 解释v编译代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2014-01-02
    • 1970-01-01
    相关资源
    最近更新 更多