Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.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大量迭代失败_Python_Parallel Processing_Iteration_Montecarlo_Pi - Fatal编程技术网

Python大量迭代失败

Python大量迭代失败,python,parallel-processing,iteration,montecarlo,pi,Python,Parallel Processing,Iteration,Montecarlo,Pi,我用Python编写了一个简单的程序,使用了多处理模块。 它工作得很好,但是当我为每个工作人员通过1E+10次迭代时,就会出现一些问题,结果是错误的。我不明白是什么问题,因为在1E+9迭代中一切都很好 import sys from multiprocessing import Pool from random import random def calculate_pi(iters): """ Worker function """ points = 0 # point

我用Python编写了一个简单的程序,使用了多处理模块。 它工作得很好,但是当我为每个工作人员通过1E+10次迭代时,就会出现一些问题,结果是错误的。我不明白是什么问题,因为在1E+9迭代中一切都很好

import sys
from multiprocessing import Pool
from random import random


def calculate_pi(iters):
    """ Worker function """

    points = 0  # points inside circle

    for i in iters:
        x = random()
        y = random()

        if x ** 2 + y ** 2 <= 1:
            points += 1

    return points


if __name__ == "__main__":

    if len(sys.argv) != 3:
        print "Usage: python pi.py workers_number iterations_per_worker"
        exit()

    procs = int(sys.argv[1])
    iters = float(sys.argv[2])  # 1E+8 is cool

    p = Pool(processes=procs)

    total = iters * procs
    total_in = 0

    for points in p.map(calculate_pi, [xrange(int(iters))] * procs):
        total_in += points

    print "Total: ", total, "In: ", total_in
    print "Pi: ", 4.0 * total_in / total
导入系统 来自多处理导入池 从随机导入随机 def计算π(iters): “工作函数” 点=0#圆内点 对于iters中的i: x=随机() y=随机()
如果x**2+y**2的话,问题似乎是多处理对它可以传递给xrange内的子进程的最大int有一个限制。下面是一个快速测试:

import sys
from multiprocessing import Pool
def doit(n):
  print n
if __name__ == "__main__":
  procs = int(sys.argv[1])
  iters = int(float(sys.argv[2]))
  p = Pool(processes=procs)
  for points in p.map(doit, [xrange(int(iters))] * procs):
    pass
现在:

这是多处理的一个更一般的问题的一部分:它依赖于标准的Python pickle,使用一些较小的(并且没有很好的文档记录)扩展来传递值。无论何时出现问题,首先要检查的是值是否按预期的方式到达

事实上,您可以通过玩
pickle
,甚至不用碰
多处理
(由于这些较小的扩展,情况并不总是这样,但通常是这样):

即使不了解pickle协议的所有细节,第一种情况下的
i100000000
显然是1E9作为int,而下一种情况下的等效块大约是1.41E9,而不是1E10作为int。您可以进行实验

一个显而易见的解决方案是传递
int(iters)
而不是
xrange(int(iters))
,并让
计算π
从其参数创建
xrange
。(注意:在某些情况下,像这样明显的转换可能会损害性能,可能会严重。但在这种情况下,它可能会稍微好一点——传递一个更简单的对象,并且您正在并行化
xrange
构造,当然差异很小,可能无关紧要。请确保在盲目思考之前进行思考。)转变。)

快速测试表明,该方法现在可以工作:

import sys
from multiprocessing import Pool

def doit(n):
  print xrange(n)

if __name__ == "__main__":
    procs = int(sys.argv[1])
    iters = int(float(sys.argv[2]))
    p = Pool(processes=procs)
    for points in p.map(doit, [iters] * procs):
      pass
然后:

但是,您仍然会遇到更大的限制:

$ ./multitest.py 2 1E100
OverflowError: Python int too large to convert to C long
同样,这也是一个基本问题。解决这个问题的一种方法是将arg作为字符串向下传递,并在子流程中执行int(float(a))

作为旁注:我之所以要做
iters=int(float(sys.argv[2])
而不是只做
iters=float(sys.argv[2])
然后再使用
int(iters)
是为了避免以后意外使用float
iters
值(与OP的版本一样,在计算
total
时,因此
total\u in/total


请记住,如果你得到足够大的数字,你会遇到C双精度类型的限制:
1E23
通常是9999999999999991611392,而不是10000000000000000。

你得到的结果是什么?@AmirRachumπ就像~0.4个迭代总数是正确的。不管
过程是什么,都会发生这种情况吗是吗?你在
过程中使用什么类型的值?为什么iters是浮点而不是int?比如说,10000.0001次迭代意味着什么?@MattiLyra没有除以
过程的数值。所以它不应该。我稍后会测试它。@abarnert for exponent.1E+NUM很有用。那么为什么100000000次迭代会给你PI估计值正确,但1410065408次迭代不正确?@MattiLyra:首先,如果你正在进行1410065408次迭代,但你认为你在进行100000000次迭代,那么你最终将导致除法错误。但我还没有测试或真正想清楚。在python 2.7.3中,我得到了
>>pickle.dumps(xrange(int(1E10)))溢出错误:Python int太大,无法在pyhton 3.2.3中转换为C long
,我得到pickle.dumps(range(int(1E10)),protocol=0)b'C\uuuuuuu内置\uuuuuuuunxrange\np0\n(L0L\nl1000000000l\nL1L\ntp1\nRp2\n.
@XavierCombelle:这不仅仅是关于2.7.3和3.2.3;它还包括32位和64位、不同的平台和编译器等。如果您的范围内的所有数字恰好都适用于您的实现,您可以忽略这个问题(除非您以后可能需要更大的范围或更高的可移植性);否则,您必须处理它。这个问题将跟踪到python核心开发中
import sys
from multiprocessing import Pool

def doit(n):
  print xrange(n)

if __name__ == "__main__":
    procs = int(sys.argv[1])
    iters = int(float(sys.argv[2]))
    p = Pool(processes=procs)
    for points in p.map(doit, [iters] * procs):
      pass
$ ./multitest.py 2 1E10
xrange(10000000000)
xrange(10000000000)
$ ./multitest.py 2 1E100
OverflowError: Python int too large to convert to C long