【问题标题】:Python: Performance when looping and manipulating a large arrayPython:循环和操作大型数组时的性能
【发布时间】:2017-03-12 07:25:07
【问题描述】:

我的问题有两个:

  1. 有没有一种方法可以有效地循环和操作 使用枚举的数组,例如 操作循环 同一时间?
  2. python 中有没有内存优化版本的数组? (如 NumPy 创建具有指定类型的较小数组)

我用Sieve of Eratosthenes 做了一个算法来查找范围(2 - rng)内的素数。

注意:如果在 2 - 1,000,000 (总运行时间也低于 1 秒)中搜索素数,则不存在此问题。在数千万和数亿中,这开始受到伤害。到目前为止,将表格从包含所有自然数更改为仅包含奇数,我能够搜索的粗略最大范围是 4 亿(奇数为 2 亿)。

虽然而不是 for 循环至少在当前算法中会降低性能。
NumPy虽然能够通过类型转换创建更小的数组,但实际上需要大约使用相同代码的处理时间加倍,除了

oddTable = np.int8(np.zeros(size))

代替

oddTable = [0] * size

并使用整数分配值“素数”和“非素数”以保持数组类型。

使用伪代码,算法如下所示:

oddTable = [0] * size    # Array representing odd numbers excluding 1 up to rng

for item in oddTable:
    if item == 0:        # Prime, since not product of any previous prime
        set item to "prime"
        set every multiple of item in oddTable to "not prime"

Python 是一种简洁的语言,尤其是在遍历列表中的每个项目时,但作为索引,比如

for i in range(1000)

无法在循环中进行操作,我不得不多次转换范围以生成要使用的可迭代对象。代码中:“P”表示素数,“_”表示非素数,0 不检查。

num = 1                  # Primes found (2 is prime)
size = int(rng / 2) - 1  # Size of table required to represent odd numbers
oddTable = [0] * size    # Array with odd numbers \ 1: [3, 5, 7, 9...]

new_rng = int((size - 1) / 3)    # To go through every 3rd item
for i in range(new_rng):         # Eliminate no % 3's
    oddTable[i * 3] = "_"
oddTable[0] = "P"                # Set 3 to prime
num += 1

def act(x):              # The actual integer index x in table refers to
    x = (x + 1) * 2 + 1
return x
        # Multiples of 2 and 3 eliminated, so all primes are 6k + 1 or 6k + 5
        # In the oddTable: remaining primes are either 3*i + 1 or 3*i + 2
        # new_rng to loop exactly 1/3 of the table length -> touch every item once
for i in range(new_rng):
    j = 3*i + 1                    # 3*i + 1
    if oddTable[j] == 0:
        num += 1
        oddTable[j] = "P"
        k = act(j)
        multiple = j + k    # The odd multiple indexes of act(j)
        while multiple < size:
            oddTable[multiple] = "_"
            multiple += k
    j += 1                         # 3*i + 2
    if oddTable[j] == 0:
        num += 1
        oddTable[j] = "P"
        k = act(j)
        multiple = j + k
        while multiple < size:
            oddTable[multiple] = "_"
            multiple += k

【问题讨论】:

  • 使用数组标准库。
  • SO 不是一个建议论坛。请澄清你的问题。如果您有两个问题,请针对 SO 提出两个单独的问题,以便轻松回答。
  • 把你的算法分成更小的块。
  • @Soviut 我觉得在问这个问题时有必要提供一些背景信息。这些问题很难独立回答,你不觉得吗?不过感谢您的建议!
  • numpy 可以更紧凑地存储值,但只有在使用快速编译 numpy 方法时才会快速。迭代的东西可能会更慢。

标签: python arrays performance python-3.x loops


【解决方案1】:

为了使您的代码更符合 Python 风格,请将您的算法拆分为更小的块(函数),以便轻松掌握每个块。

我的第二条评论可能会让您大吃一惊:Python 带有“包含电池”。为了给你的 Erathostenes' Sieve 编程,为什么你需要显式地操作数组并用它污染你的代码?为什么不创建一个函数(例如 is_prime)并使用为此目的提供的standard memoize decorator? (如果您坚持使用 2.7,另请参阅memoization library for python 2.7)。

上面两条建议的结果可能不是“最有效的”,但它会(正如我对那个确切问题的经验)工作得很好,同时允许您快速创建可以节省程序员的时尚代码时间(用于创建和维护)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2019-03-05
    • 2013-05-08
    • 1970-01-01
    相关资源
    最近更新 更多