Я не уверен, что это дубликат других вопросов памяти PyPy, но здесь я приведу конкретный пример.
from __future__ import division
def mul_inv(a, m):
"""Modular multiplicative inverse, a^-1 mod m. Credit: rosettacode.org"""
m0 = m
x0, x1 = 0, 1
if m == 1: return 1
while a > 1:
assert m != 0, "a and m must be coprime"
q = a // m
a, m = m, a%m
x0, x1 = x1 - q * x0, x0
if x1 < 0: x1 += m0
return x1
M = 1000000009
L = 10**8
bin2 = [0] * L
bin2[0] = 1
for n in range(L-1):
bin2[n+1] = (bin2[n] * (4*n + 2) * mul_inv(n+1, M)) % M
if n % 10**5 == 0: print(n, bin2[n])
print(bin2[:20])
С python 3.6 программа использует не более 3-4 ГБ и работает до завершения (изменение списка Армина Риго не меняет этого существенно). С python 2.7.13 с PyPy 5.10.0 программа быстро достигает 8 ГБ (сколько у меня оперативной памяти) и зависает. Даже при вызовах gc.collect()
программе не хватает памяти, когда n
составляет около 3,5 * 10 ^ 7.
Откуда это использование памяти? Единственным большим использованием памяти должно быть инициализация bin2
как списка 10 ^ 8 int. Ничто другое не должно увеличивать использование памяти при условии, что все локальные переменные в mul_inv
собираются сборщиком мусора.
range(L-1)
создаст список размером не менее10**8*24
байтов, поскольку каждыйint
объект требует около24
байтов в CPython, не уверен в PyPy. Так что попробуйте сxrange
. - person juanpa.arrivillaga   schedule 04.09.2018for i in range(x)
, чтобы фактически не материализовать весь список. - person juanpa.arrivillaga   schedule 04.09.2018range
никогда раньше не был для меня проблемой. Например, у меня есть функция Sieve of Eratosthenes, которая без проблем делает что-то вродеrange(10**8)
. - person qwr   schedule 04.09.2018Nothing else should be increasing the memory usage
- ну нет, каждый новый объектlong
, хранящийся в списке, требует дополнительной памяти. - person Armin Rigo   schedule 05.09.2018