代码之家  ›  专栏  ›  技术社区  ›  elm

基于蒙特卡罗的Pi计算的Python高效矢量化

  •  3
  • elm  · 技术社区  · 11 年前

    为了近似Pi的值,考虑用随机值填充阵列的这种随机方法,

    import random as rd
    import numpy as np
    
    def r(_): return rd.random()
    
    def np_pi(n):
        v_r = np.vectorize(r)
        x = v_r(np.zeros(n))
        y = v_r(np.zeros(n))
    
        return sum (x*x + y*y <= 1) * 4. / n
    

    注意,随机数生成依赖于Python标准库;尽管考虑numpy随机生成,

    def np_pi(n):
       x = np.random.random(n)
       y = np.random.random(n)
    
        return sum (x*x + y*y <= 1) * 4. / n
    

    现在考虑非矢量化方法,

    import random as rd
    
    def dart_board():
        x,y = rd.random(), rd.random()
        return (x*x + y*y <= 1)
    
    def pi(n):
        s = sum([dart_board() for _ in range(n)])
        return s * 4. / n
    

    事实证明,非矢量化形式的平均速度比矢量化形式快4倍,例如考虑 n = 5000000 操作系统命令行如下(Python 2.7、Quadcore、8GB RAM、RedHat Linux),

    time python pi.py
    time python np_pi.py
    

    从而提出如何改进矢量化方法以提高其性能。

    1 回复  |  直到 11 年前
        1
  •  5
  •   Oliver W.    11 年前

    您正在调用 python内置 sum ,而不是numpy的矢量化方法 总和 :

    import numpy as np
    import random as rd
    
    def np_pi(n):
        x = np.random.random(n)
        y = np.random.random(n)
    
        return (x*x + y*y <= 1).sum()
    
    def dart_board():
        x,y = rd.random(), rd.random()
        return (x*x + y*y <= 1)
    
    def pi(n):
        s = sum([dart_board() for _ in range(n)])
    

    时间结果现在大不相同:

    In [12]: %timeit np_pi(10000)
    1000 loops, best of 3: 250 us per loop
    
    In [13]: %timeit pi(10000)
    100 loops, best of 3: 3.54 ms per loop
    

    我想 总和 在numpy数组上进行迭代而不是使用矢量化例程会导致开销。