Python:循环和操作大型数组时的性能

时间:2016-10-29 16:50:35

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

我的问题是双重的:

  1. 有没有办法有效地循环和操纵 使用枚举的数组,例如操纵循环 同时?
  2. python中是否有任何内存优化版本的数组? (比如NumPy创建具有指定类型的较小数组)
  3. 我做了一个算法,用Sieve of Eratosthenes在范围(2 - rng)中查找素数。

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

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

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

    取代

    oddTable = [0] * size
    

    并使用整数分配值" prime"并且"不是素数"保持数组类型。

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

    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
    

1 个答案:

答案 0 :(得分:0)

要使代码更加pythonic,请将算法拆分为较小的块(函数),以便可以轻松地抓取每个块。

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

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