Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多线程Pi计算(无加速-怎么办)_Python_Multithreading_Pi - Fatal编程技术网

Python 多线程Pi计算(无加速-怎么办)

Python 多线程Pi计算(无加速-怎么办),python,multithreading,pi,Python,Multithreading,Pi,我试图使用Ramanujan的公式之一在Python上以任意精度计算pi:。它基本上需要大量的阶乘和高精度的浮点数除法 我使用多个线程来划分无穷级数计算,当除以线程数时,给每个线程所有具有一定模数的成员。所以如果你有3个线程,总和应该像这样被分割 线程1--->1,4,7。。。成员 线程2-->2、5、8。。。 线程3-->3、6、9 以下是我目前的代码: from decimal import * from math import sqrt, ceil from time

我试图使用Ramanujan的公式之一在Python上以任意精度计算pi:。它基本上需要大量的阶乘和高精度的浮点数除法

我使用多个线程来划分无穷级数计算,当除以线程数时,给每个线程所有具有一定模数的成员。所以如果你有3个线程,总和应该像这样被分割 线程1--->1,4,7。。。成员 线程2-->2、5、8。。。 线程3-->3、6、9

以下是我目前的代码:

from decimal   import *
from math      import sqrt, ceil
from time      import clock
from threading import *
import argparse

memoizedFactorials = []
memoizedFactorials.append( 1 )
memoizedFactorials.append( 1 )

class Accumulator:
    def __init__( self ):
        self._sum = Decimal( 0 )

    def accumulate( self, decimal ):
        self._sum += decimal

    def sum( self ):
        return self._sum

def factorial( k ):
    if k < 2: return 1
    elif len(memoizedFactorials) <= k:
        product = memoizedFactorials[ - 1 ] #last element 
        for i in range ( len(memoizedFactorials), k+1 ):
            product *= i;
            memoizedFactorials.append(product)

    return memoizedFactorials[ k ]

class Worker(Thread):
    def __init__( self, startIndex, step, precision, accumulator ):
        Thread.__init__( self, name = ("Thread - {0}".format( startIndex ) ) )
        self._startIndex = startIndex
        self._step = step
        self._precision = precision
        self._accumulator = accumulator

    def run( self ):
        sum = Decimal( 0 )
        result = Decimal( 1 )
        zero = Decimal( 0 )

        delta = Decimal(1)/( Decimal(10)**self._precision + 1 )
        #print "Delta - {0}".format( delta ) 
        i = self._startIndex
        while( result - zero > delta ):
            numerator = Decimal(factorial(4 * i)*(1103 + 26390 * i))
            denominator = Decimal((factorial(i)**4)*(396**(4*i)))
            result =  numerator / denominator
            print "Thread - {2} --- Iteration - {0:3} --->{1:3}".format( i, result, self._startIndex )
            sum += result
            i += self._step

        self._accumulator.accumulate( sum ) 
        print 

def main( args ):
    numberOfDigits = args.numberOfDigits;
    getcontext().prec = numberOfDigits + 8
    zero = Decimal(1) / Decimal( 10**( numberOfDigits + 1 ) )

    start = clock()
    accumulator = Accumulator()

    threadsCount = args.numberOfThreads;
    threadPool = []
    for i in range(0, threadsCount ):
        worker = Worker( i, threadsCount, numberOfDigits, accumulator )
        worker.start()
        threadPool.append( worker )

    for worker in threadPool:
        worker.join()

    sum = accumulator.sum();

    rootOfTwo = Decimal(2).sqrt()

    result = Decimal( 9801 ) / ( Decimal( 2 ) * rootOfTwo * sum ) 
    end = clock();

    delta = end - start;

    print result;
    print ("Took it {0} second to finish".format( delta ) )

    #testing the results
    #realPiFile = open("pi.txt");
    #myPi = str(result)
    #realPi = realPiFile.read( len(myPi) - 1 )

    #if ( myPi[:-1] != realPi ):
    #    print "Answer not correct!"
    #    print "My pi   - {0}".format(myPi)
    #    print "Real pi - {0}".format(realPi)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description = 'Calculate Pi at with arbitrary precision')
    parser.add_argument('-p',            dest = 'numberOfDigits',  default=20, type = int, help ='Number of digits in pi ')
    parser.add_argument('-t', '--tasks', dest = 'numberOfThreads', default=1,  type = int, help ='Number of tasks( threads )')
    parser.add_argument('-o',            dest = 'outputFileName',  type = str,             help ='Connect to VCS testing servers')
    parser.add_argument('-q', '--quet',  dest = 'quetMode'      ,  action='store_true',    help ='Run in quet mode')

    args = parser.parse_args()

    print args
    main(args)
    a = raw_input("Press any key to continue...")
从十进制导入*
来自数学导入sqrt,ceil
从时间输入时钟
从线程导入*
导入argparse
memoizedFactorials=[]
memorizedFactorials.append(1)
memorizedFactorials.append(1)
类别累加器:
定义初始化(自):
自和=十进制(0)
def累积(自身,十进制):
自身._总和+=十进制
定义和(自身):
返回自我
def阶乘(k):
如果k<2:返回1
elif len(记忆因子)增量:
分子=十进制(阶乘(4*i)*(1103+26390*i))
分母=十进制((阶乘(i)**4)*(396**(4*i)))
结果=分子/分母
打印“线程-{2}---Iteration-{0:3}--->{1:3}”。格式(i,result,self.\u startIndex)
总和+=结果
i+=自身.\u步
自积累(总和)
印刷品
def主(args):
numberOfDigits=args.numberOfDigits;
getcontext().prec=numberOfDigits+8
零=十进制(1)/十进制(10**(数字位数+1))
开始=时钟()
累加器=累加器()
threadscont=args.numberOfThreads;
线程池=[]
对于范围内的i(0,螺纹孔型):
辅助工=辅助工(i,螺纹孔,numberOfDigits,累加器)
worker.start()
threadPool.append(辅助线程)
对于线程池中的工作线程:
worker.join()
sum=累加器。sum();
rootOfTwo=Decimal(2).sqrt()
结果=小数点(9801)/(小数点(2)*两个根*和)
结束=时钟();
delta=结束-开始;
打印结果;
打印(“花了{0}秒才完成”。格式(增量))
#测试结果
#realPiFile=open(“pi.txt”);
#myPi=str(结果)
#realPi=realPiFile.read(len(myPi)-1)
#如果(myPi[:-1]!=realPi):
#打印“回答不正确!”
#打印“我的pi-{0}”。格式(myPi)
#打印“realPi-{0}”。格式(realPi)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
parser=argparse.ArgumentParser(description='Calculate Pi at with arbitral precision')
add_参数('-p',dest='numberOfDigits',default=20,type=int,help='pi中的位数')
add_参数('-t','-tasks',dest='numberOfThreads',default=1,type=int,help='numberoftasks(threads)'
parser.add_参数('-o',dest='outputFileName',type=str,help='Connect to VCS testing servers')
parser.add_参数('-q','-quet',dest='quetMode',action='store_true',help='在quet模式下运行〕
args=parser.parse_args()
打印参数
主(args)
a=原始输入(“按任意键继续…”)
让我担心的是,当使用多个线程时,我在时间上的加速度很小或没有。例如,1000位pi: 1线程-->0.68秒 2线程-->0.74秒 4线程-->0.75秒 10个线程-->0.96秒

你对如何减少时间有什么想法吗。我在TaskManager上看到,当使用四个线程时,我的两个内核都100%地参与其中。然而,时间似乎是一样的

附言:这是家庭作业,所以我不能用其他公式。PSS:我正在使用python 2.7


谢谢:)

由于GIL(全局解释锁),线程无法加快速度。用于此类任务。它的用法与线程非常相似。

Python有一个GIL(),它可以防止多个线程同时执行Python代码,也就是说,使用多个线程无法提高CPU受限任务的速度。您必须使用多个进程。

相反,要通过序列和所有这些讨厌的阶乘强行通过,您肯定会了解二进制分割算法

这家伙已经帮你做了。它有应用于Chudnovsky公式的二进制拆分结构的python实现:


这种结构的主要优点是,在计算级数时不需要除法、阶乘和任何浮点计算。然后你在分子和分母之间进行一次,最后一次,超大质量的除法。实际上,我不知道如何多线程处理它,但这只是一个开始。

好吧,这不是全部事实。如果每个线程都使用数字执行计算任务,那么您可以使用
numpy
执行。如果正确使用,
numpy
将“潜入”C代码,而在那里它会释放所有锁,并且永远不会获得它们,因此,从技术上讲,可以使用Python线程进行繁重的计算。“由于GIL,线程不会加快速度。”(此处的目的)是针对OP解决方案。OPs代码中没有NumPy。我的评论只是一些额外的信息,供您在这个特殊情况下绝对正确地回答。谢谢,它在处理过程中发挥了巨大的作用。代码的变化很小:)顺便说一句,
decimal
模块在Python3.3中快了30倍