【问题标题】:Why is list multiplication so fast?为什么列表乘法这么快?
【发布时间】:2016-06-08 15:12:51
【问题描述】:

在创建列表时,我认为尽可能推荐理解,因为它是最快的。但是你瞧。

In [1]: %timeit -n1000 [0]*1000000
1000 loops, best of 3: 2.3 ms per loop

In [2]: %timeit -n1000 [0 for _ in range(1000000)]
1000 loops, best of 3: 27.1 ms per loop

In [3]: a = np.zeros(1000000, dtype=int)

In [4]: %timeit -n1000 a.tolist()
1000 loops, best of 3: 7.93 ms per loop

即使numpy.ndarray.tolist 也跟不上乘法。这是为什么呢?

【问题讨论】:

  • #2 实际上运行了一个 python 循环,而 #1 完全解释为没有任何 python 循环。

标签: python performance python-3.x


【解决方案1】:

dis 模块可用于比较前两种方法。

def list_mult():
    return [0]*1000000

dis.dis(list_mult)
#  2           0 LOAD_CONST               1 (0)
#              3 BUILD_LIST               1
#              6 LOAD_CONST               2 (1000000)
#              9 BINARY_MULTIPLY     
#             10 RETURN_VALUE        

这里使用了BINARY_MULTIPLY 指令。另一方面...

def list_range():
    return [0 for _ in range(1000000)]

dis.dis(list_range)
# 2           0 BUILD_LIST               0
#             3 LOAD_GLOBAL              0 (range)
#             6 LOAD_CONST               1 (1000000)
#             9 CALL_FUNCTION            1
#            12 GET_ITER            
#       >>   13 FOR_ITER                12 (to 28)
#            16 STORE_FAST               0 (_)
#            19 LOAD_CONST               2 (0)
#            22 LIST_APPEND              2
#            25 JUMP_ABSOLUTE           13
#       >>   28 RETURN_VALUE    

此函数显式构造一个循环,然后在每次迭代中加载 0 并将其附加到工作列表中。这会慢很多。

需要注意的是,这两种构造方法并不等价,尤其是当列表内的值是可变的时。例如,[object()] * 10 将为您提供包含 10 个相同对象的列表,而[object() for _ in range(10)] 将为您提供包含 10 个不同对象的列表。

关于numpy 的例子,这个操作是numpy 的最坏情况。在构造和转换numpy 数组时有很多开销,以便可以快速进行矢量化操作(如 cmets 中所述)。

【讨论】:

    【解决方案2】:

    在第一种情况下,python 可以创建一个列表,其中所有的零都指向同一个id。这很好用,因为原语是 literal,但如果你传递一个对象,它就不会按预期工作。在这种情况下,每个元素实际上都是对同一个对象的引用。

    range 的情况下,会进行函数调用,因此会产生更多开销。

    【讨论】:

      猜你喜欢
      • 2017-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2018-03-22
      • 2021-12-19
      相关资源
      最近更新 更多