首页 > 解决方案 > 如何在 Numpy 中重写双循环以节省执行时间?

问题描述

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

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

这段代码将被执行数百万次,所以我想使用 Numpy 对其进行优化。

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

标签: pythonarraysnumpymultidimensional-array

解决方案


有人在评论中击败了我,但我有一些时间信息给你。请注意,您的时间可能会有所不同,但相对时间应该相当能代表您可能看到的性能。

首先是您的代码,我将其修复为可运行:

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 设置理想的东西。我仍然建议在您的系统上尝试它(使用%%timeitJupyter 笔记本中的单元魔法以便于分析)。

接下来使用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 倍!


推荐阅读