尝试使用gmpy在Python中计算大数。Python不断崩溃?

尝试使用gmpy在Python中计算大数。Python不断崩溃?,python,memory-management,memory-leaks,gmp,Python,Memory Management,Memory Leaks,Gmp,有人建议我使用gmpy来帮助高效地计算大量的数字。在我使用python之前,我的脚本运行了一两天,然后内存耗尽(不确定这是怎么发生的,因为我的程序的内存使用在整个过程中基本上是恒定的……可能是内存泄漏?) 无论如何,在运行我的程序几秒钟后,我一直遇到这个奇怪的错误: mp_allocate< 545275904->545275904 > Fatal Python error: mp_allocate failure This application has requested

有人建议我使用gmpy来帮助高效地计算大量的数字。在我使用python之前,我的脚本运行了一两天,然后内存耗尽(不确定这是怎么发生的,因为我的程序的内存使用在整个过程中基本上是恒定的……可能是内存泄漏?)

无论如何,在运行我的程序几秒钟后,我一直遇到这个奇怪的错误:

mp_allocate< 545275904->545275904 >
Fatal Python error: mp_allocate failure

This application has requested the Runtime to terminate it in an unusual way. 
Please contact the application's support team for more information.
我有10 Gig的RAM,如果没有gmpy,这个脚本可以运行数天而不会耗尽内存(考虑到
s
从未真正变大,仍然不确定这是怎么发生的)

有人有什么想法吗


编辑:忘记提及我正在使用Python 3.2

免责声明:我是gmpy和gmpy2的维护者。

我要到今晚才能测试这个。但是有一些评论和问题

不要使用(s*s)%M,而是使用pow(s,2,M)。它应该更快

如果使用gmpy2.mpz()而不是gmpy2.xmpz(),会发生什么情况

您运行的是64位版本的Python和gmpy2吗?(我想是的,但我只想确认一下。)

关于range和xrange,在Python3.x中,range已经取代了xrange

使用附加信息进行编辑。

崩溃的原因是32位构建中的内部结构溢出。使用64位版本的Python和gmpy或gmpy2是正确的修复方法

unpack(x,n)函数类似于字符串的split():它将一个数字划分为一系列n位值。它相当于,但比:

def unpack(x,n):
r = []
m = 2**n
while x:
    x, temp = divmod(x,m)
    r.append(temp)
return r
一些文档可以通过
帮助(gmpy2.unpack)
获得,但更好的文档在我的待办事项列表中

unpack()可以用来消除%运算的原因与添加基数为10的数字以检查9的可整除性相同。在这种情况下,unpack()创建p位数字,我们将除以2**p-1

下面是一些测试代码:

import gmpy2
import time

def mersenne1(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses native Python longs. Does not verify that p is prime.'''

    s = 4
    M = 2**p - 1
    for i in range(p-2):
        s = ((s*s)-2) % M
    return False if s else True

def mersenne2(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses gmpy2.mpz. Does not verify that p is prime.'''

    s = gmpy2.mpz(4)
    M = gmpy2.mpz(2)**p - 1
    for i in range(p-2):
        s = ((s*s)-2) % M
    return False if s else True

def mersenne3(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses gmpy2.mpz and no mod. Does not verify that p is prime.'''

    s = gmpy2.mpz(4)
    M = gmpy2.mpz(2)**p - 1
    for i in range(p-2):
        s = (s*s)
        s = sum(gmpy2.unpack(s, p))
        s = sum(gmpy2.unpack(s, p))
        if s < 2:
            s = M - 2 + s
        else:
            s = s - 2
    return False if s else True

if __name__ == "__main__":
    p = 44497

    start = time.time()
    result1 = mersenne1(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    start = time.time()
    result2 = mersenne2(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    start = time.time()
    result3 = mersenne3(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    if result1 == result2 == result3:
        print("All three tests are equal!")
    else:
        print("Oops, something has gone wrong.")

你使用的是什么版本的Python?哦,是的,这是
***
,而不是
*
。忽略了这一点。很好。@RichieHindle是对的;另外,如果你使用的是Python 2,请使用
xrange
而不是
range
。在Python 2中,
range
返回一个列表,在这种情况下,它将包含3000000000个元素,甚至f或者10 GB的内存。@TomZych:我使用的是Python 3,显然xrange不存在?然后这就是@RichieHindle评论中的答案,该评论莫名其妙地消失了。他指出,
2**30000000000
可能太大,无法放入您机器的地址空间。用10亿试试看是否有效。谢谢您的回复.python和gmpy的64位版本调用得很好。这似乎解决了问题。另外,我想我不能使用
pow(s,2,M)
,因为我实际的代码行是
s=((s*s)-2)%M
。为了代码示例的简单性,我刚刚省略了它。ISTR gmp有某种幂模函数?@RyanPeschel它看起来像是在寻找梅森素数。如果是这样,用一些附加值替换%应该可以显著提高性能。如果M=2**n-1,那么x%M可以通过将x拆分为n位块来计算s并添加块。您需要重复split/add两次,但对于较大的n会更快。命令将是
x=sum(gmpy2.unpack(x,n))
。尝试一下这个提示,我可以稍后发布一个示例。@casevh:是的!我也非常感谢您提供一个关于如何进一步优化它的示例。我试图在文档中查找unpack,但似乎找不到任何相关内容。另外,当我使用xmpz时,它会给我一个错误,说它需要ints。啊,显然如果我使用mpz而不是xmpz来运行解包。尽管如此,我还是不确定解包的作用,因为我似乎找不到关于它们的任何文档。
import gmpy2
import time

def mersenne1(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses native Python longs. Does not verify that p is prime.'''

    s = 4
    M = 2**p - 1
    for i in range(p-2):
        s = ((s*s)-2) % M
    return False if s else True

def mersenne2(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses gmpy2.mpz. Does not verify that p is prime.'''

    s = gmpy2.mpz(4)
    M = gmpy2.mpz(2)**p - 1
    for i in range(p-2):
        s = ((s*s)-2) % M
    return False if s else True

def mersenne3(p):
    '''Primality test for Mersenne prime: 2**p -1.
    Uses gmpy2.mpz and no mod. Does not verify that p is prime.'''

    s = gmpy2.mpz(4)
    M = gmpy2.mpz(2)**p - 1
    for i in range(p-2):
        s = (s*s)
        s = sum(gmpy2.unpack(s, p))
        s = sum(gmpy2.unpack(s, p))
        if s < 2:
            s = M - 2 + s
        else:
            s = s - 2
    return False if s else True

if __name__ == "__main__":
    p = 44497

    start = time.time()
    result1 = mersenne1(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    start = time.time()
    result2 = mersenne2(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    start = time.time()
    result3 = mersenne3(p)
    print("Elapsed time: {:6.3f}".format(time.time() - start))

    if result1 == result2 == result3:
        print("All three tests are equal!")
    else:
        print("Oops, something has gone wrong.")
C:\x64\Python32>python.exe mersenne.py
Elapsed time: 163.683
Elapsed time: 12.782
Elapsed time:  3.630
All three tests are equal!