如何在Numpy中重写double for循环以节省执行时间?

时间:2019-01-31 19:22:26

标签: python arrays numpy multidimensional-array

我想以最有效的方式创建一个卡片组。这是带有double for循环和标准列表的简单解决方案:

card = []
for figure in range(2, 15):
    for suite in [1, 2, 3, 4]:
        card = [figure, suite]
        self.cards.append(card)

此代码将执行数百万次,因此我想使用Numpy对其进行优化。

EDIT1:我什至认为是否写下所有可能性并将它们放入数组中并不是最快的。

1 个答案:

答案 0 :(得分:3)

有人打我给它的意见,但我有一些对你的计时信息。请注意,您的时间可能会有所不同,但是相对时间应该可以很好地代表您可能会看到的性能。

首先您的代码,这是我的固定,使可运行:

cards = []
for figure in range(2, 15):
    for suite in [1, 2, 3, 4]:
        card = [figure, suite]
        cards.append(card)
# 8.04 µs ± 27.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

因此,需要花8.04微秒!使用numpy.mgrid

import numpy as np
cards = np.mgrid[1:5, 2:15]
# 20.5 µs ± 320 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

出人意料地慢得多。我想知道在我的系统上是否没有为numpy设置理想的设置。我还是建议您尝试在系统上(使用%%timeit细胞在Jupyter笔记本电脑,便于分析魔法)。

接下来使用itertools.product

import itertools as it
figures = range(2, 15)
suits = [1, 2, 3, 4]
cards = list(it.product(suits, figures))
# 2.5 µs ± 27.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

更快!最好的消息是it.product()返回一个迭代器,而不是在调用时创建列表,因此,如果您直到以后都不需要实际的卡列表,则可以推迟创建列表,而只需传递迭代器即可。创建迭代是最快迄今为止:

cards_it = it.product(suits, figures)  # notice no 'list'
# 479 ns ± 9.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

那比其他任何东西快5到10倍!