Python 基于 Monte Carlo 的 Pi 计算的高效矢量化
Python efficient vectorization for Monte Carlo based Pi calculation
为了近似 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
和 OS 命令行如下(Python 2.7,四核,8GB内存,RedHat Linux),
time python pi.py
time python np_pi.py
因此请教如何改进矢量化方法以提高其性能。
您正在调用 python 内置函数 sum
,而不是 numpy 的向量化方法 sum
:
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 数组上调用内置函数 sum
会通过遍历数组而不是使用矢量化例程导致开销。
为了近似 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
和 OS 命令行如下(Python 2.7,四核,8GB内存,RedHat Linux),
time python pi.py
time python np_pi.py
因此请教如何改进矢量化方法以提高其性能。
您正在调用 python 内置函数 sum
,而不是 numpy 的向量化方法 sum
:
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 数组上调用内置函数 sum
会通过遍历数组而不是使用矢量化例程导致开销。