【问题标题】:How to make iterating faster?如何让迭代更快?
【发布时间】:2021-07-31 00:53:02
【问题描述】:

我有这个循环:

for i in range(self.worldWidth):
    for j in range(self.worldHeight):
        originalValue = self.world.world[i, j]
        # Process newValue
        self.world.world[i, j] = newValue
        

当世界大小为 (500, 500) 时,它每秒运行大约 10 次,这对于我正在做的事情来说很慢,当我尝试在 C# 中做同样的事情时,我得到了三倍的速度(每次 30 次第二)。
有没有办法让它更快?

注意:这些速度是在没有对值做任何事情的情况下计算出来的

编辑:在用 C# 进一步测试后,我得到了大约 10 倍的速度(只是第一次很慢),但在 python 中每次大约 0.07 秒

【问题讨论】:

  • 世界是如何定义的?更准确地说,它的类型是什么?
  • 这大约是 Python 与 C# 的数量级差异。
  • 你为什么要在ij 上循环?为什么不直接迭代self.world.world
  • self.world 是一个 World 类型的对象,它有一个名为 world (self.world.world) 的字段,它是世界保存的数据(0 到 1 之间的双精度数),抱歉混淆命名
  • 听着,如果您想要关于如何加快代码速度的有效建议,您需要实际告诉我们您在做什么。

标签: python numpy loops iteration


【解决方案1】:

在不知道您要做什么但将 numpy 标记作为指标的情况下。 Numpy 在编译后的代码中运行它的内部循环,因此比使用显式 Python 循环要快得多。

import numpy as np

world = np.zeros( ( 500, 500 ) )

world[:] = 42

def test( world, v ):
    for r, row in enumerate( world ):
        for c, col in enumerate( row ):
            world[ r, c ] = v 

test( world, 42 )

%timeit world[:] = 42                                                   
# %timeit 110 µs ± 1.58 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit test( world, 43 )                                               
# 69.9 ms ± 1.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

如果您需要计算,如果它们可以在 numpy 中定义,它们也可以更快。

weight = np.arange( 500 )/250

def test_loop( world, weight ):
    w = world.copy()
    for r, row in enumerate( world ):
        for c, col in enumerate( row ):
            w[ r, c ] *= weight[c]
    return w

test_loop( world, weight )

def test_np( world, weight ):
    w = world.copy()
    return world * weight

np.isclose( test_loop( world, weight ),test_np( world, weight )).all()
# True  # The two results are equivalent.

%timeit test_np( world, weight )                                        
# 754 µs ± 1.71 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit test_loop( world, weight )                                      
# 172 ms ± 3.62 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

正如一些 cmets 所暗示的那样。这取决于生成newValue 所需的计算。鉴于计算时间的潜在改进,可能值得为您的应用程序探索 numpy。

【讨论】:

    【解决方案2】:

    也许可以通过使用 range 关键字将 self.worldWidthself.worldHeight 声明为插入数字的列表。 这将保存每次迭代的 next() 数的计算。

    注意 - 与使用循环中下一个索引计算的范围选项相比,这种方式会导致内存浪费。

    【讨论】:

    • 没看懂,能不能举个例子
    • @HamzaNasab 他说迭代 list 比迭代 range 对象更快,这是真的。
    • 注意,range 对象不是迭代器
    • @juanpa.arrivillaga 是真的。如果a = range(10) next(a) a 不是迭代器,我会修正我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 2011-05-11
    相关资源
    最近更新 更多