Python PI和x3C0;计算加载系统

Python PI和x3C0;计算加载系统,python,math,pi,Python,Math,Pi,感谢您花时间阅读并(希望)回答我的问题!我最近对π感兴趣(π不是可食用的类型,我已经喜欢了!),并且对这个数字的计算很感兴趣,我可以流利地输入中等程度的python,并且是一个高级Linux用户,因此我建立了一个由旧(ish)计算机组成的“集群”。经过一番挖掘,我发现了一个计算pi的python程序,我对它进行了编辑,并将其输出到一个文件中,我在其中一台计算机上运行了它,它的工作令人惊讶,目前大约有200万位数的pi(与22.7万亿的世界记录相比非常小!),并且使用了100%的内核和94%的ra

感谢您花时间阅读并(希望)回答我的问题!我最近对π感兴趣(π不是可食用的类型,我已经喜欢了!),并且对这个数字的计算很感兴趣,我可以流利地输入中等程度的python,并且是一个高级Linux用户,因此我建立了一个由旧(ish)计算机组成的“集群”。经过一番挖掘,我发现了一个计算pi的python程序,我对它进行了编辑,并将其输出到一个文件中,我在其中一台计算机上运行了它,它的工作令人惊讶,目前大约有200万位数的pi(与22.7万亿的世界记录相比非常小!),并且使用了100%的内核和94%的ram,我唯一的问题是我不能取消这个过程,或者我必须从头开始,我试图理解这个算法,这样我就可以在加载函数中编码。加载函数应打开该文件,并从该文件开始继续计算pi。我能稍微理解这个算法,并且已经计算出它使用已经计算的pi数字来计算数字(这解释了速度衰减),因此加载预先计算的数据是可能的。代码如下:

import sys


def calcPi():
    q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
    while True:
        if 4*q+r-t < n*t:
            yield n
            nr = 10*(r-n*t)
            n  = ((10*(3*q+r))//t)-10*n
            q  *= 10
            r  = nr
        else:
            nr = (2*q+r)*l
            nn = (q*(7*k)+2+(r*l))//(t*l)
            q  *= k
            t  *= l
            l  += 2
            k += 1
            n  = nn
            r  = nr

pi_digits = calcPi()
i = 0
for d in pi_digits:
    sys.stdout =open("piDigits.txt", "a")
    sys.stdout.write(str(d))
    i += 1
    if i == 50:
        print("")
        i = 0
导入系统 def calcPi(): q、 r,t,k,n,l=1,0,1,1,3,3 尽管如此: 如果4*q+r-t 如果有人能帮我找到一种方法,加载预先计算好的pi数字,然后继续计算,或者向我解释算法/代码,我将不胜感激! 提前谢谢。
-利奥·科尼利厄斯(Leo Cornelius)

您正在使用的代码中有一个生成器。这是一个带有“yield”语句的函数。它们所做的是在调用时生成一个值,然后等待直到再次调用它们(通常在循环中),然后计算下一个值,然后生成该值。因为你在一个无限循环中计算一个无限数,程序会一直运行直到你杀死它,然后你就会失去状态。所以,您需要一种方法来保持状态


我建议您实现一个迭代器来替换生成器。迭代器类似于生成器,但它不是函数,而是对象。所以它有状态。也就是说,您可以将所有这些变量(nr、nn、q等)的当前值存储为“实例”变量。然后,当您想要终止时,可以使用“pickle”库持久化类的当前状态。然后,要在脚本停止的地方继续脚本,请加载pickle文件以完全按照程序终止前的状态重建对象。

您需要的是转储并恢复
calcPi
生成器的整个状态。幸运的是,所有状态都在第一行中明确指定。下面是一个原型,向您展示这个想法:

import sys
import os.path


def calcPi(state=None):
    if state is None:
        q, r, t, k, n, l = 1, 0, 1, 1, 3, 3
        skip_first = False
    else:
        q, r, t, k, n, l = state
        skip_first = True
    while True:
        if 4 * q + r - t < n * t:
            # have to skip the first yield in the "restore state" scenario because
            # this is the same we returned the last time from this state
            if not skip_first:
                state = q, r, t, k, n, l
                yield n, state
            else:
                skip_first = False
            nr = 10 * (r - n * t)
            n = ((10 * (3 * q + r)) // t) - 10 * n
            q *= 10
            r = nr
        else:
            nr = (2 * q + r) * l
            nn = (q * (7 * k) + 2 + (r * l)) // (t * l)
            q *= k
            t *= l
            l += 2
            k += 1
            n = nn
            r = nr


initial_state = None
total_digit_cnt = 0
buf_digit_cnt = 0
state_file_name = "piState.txt"
if os.path.isfile(state_file_name):
    with open(state_file_name, "r+") as stateF:
        lines = stateF.readlines()
        if len(lines) > 0:
            last_line = lines[-1]
            # truncate the old state and save only the few last last lines
            stateF.seek(0)
            stateF.truncate(0)
            stateF.write(lines[-3])
            stateF.write(lines[-2])
            stateF.write(last_line)
            initial_state = map(long, last_line.replace('(', '').replace(')', '').split(','))
            total_digit_cnt = initial_state[-1]
            initial_state = initial_state[:-1]

if initial_state is not None:
    print str((total_digit_cnt, initial_state))

pi_digits = calcPi(initial_state)
buf = ""
state_cnt = 0
with open("piDigits.txt", "a") as outF:
    with open(state_file_name, "a+") as stateF:
        for digit, state in pi_digits:
            buf += str(digit)
            buf_digit_cnt += 1
            total_digit_cnt += 1

            if buf_digit_cnt == 500:
                print "Start dumping state %d" % state_cnt
                buf_digit_cnt = 0
                outF.write(buf)
                buf = ""
                outF.write("\n")
                outF.flush()
                # as states take much more space, clear old states
                state_cnt += 1
                if state_cnt % 50 == 0:
                    stateF.seek(0)
                    stateF.truncate(0)
                stateF.write(str((state, total_digit_cnt)) + "\n")
                stateF.flush()
                print "End dumping state %d" % state_cnt
导入系统 导入操作系统路径 def calcPi(状态=无): 如果状态为“无”: q、 r,t,k,n,l=1,0,1,1,3,3 先跳过\u=错误 其他: q、 r,t,k,n,l=状态 先跳过=真 尽管如此: 如果4*q+r-t0: 最后一行=行[-1] #截断旧状态并仅保存最后几行 stateF.seek(0) stateF.truncate(0) stateF.write(第[-3]行) stateF.write(第[-2]行) stateF.write(最后一行) 初始状态=映射(长,最后一行。替换('(','')。替换('),'')。拆分(',')) 总数字=初始状态[-1] 初始状态=初始状态[:-1] 如果初始_状态不是无: 打印str((总数字,初始状态)) pi_位数=calcPi(初始状态) buf=“” 状态_cnt=0 以open(“piDigits.txt”、“a”)作为输出: 打开(状态文件名为“a+”)作为状态F: 对于数字,以pi_数字表示: buf+=str(位数) buf_数字_cnt+=1 总数字=1 如果buf_digit_cnt==500: 打印“开始转储状态%d”%state\u cnt buf\u数字\u cnt=0 输出写入(buf) buf=“” 输出写入(“\n”) 冲水 #由于状态占用更多空间,请清除旧状态 状态_cnt+=1 如果状态为%50==0: stateF.seek(0) stateF.truncate(0) stateF.write(str((状态,总位数))+“\n”) stateF.flush() 打印“结束转储状态%d”%state\u cnt 其思想是不仅返回下一个数字,还从生成器返回整个状态,并定期将其转储到另一个文件中。这只是一个原型。在真正的代码中进行处理