Numpy与for循环执行效率
— Python — 3 min read
这是我在了解蒙特卡罗算法时,对于使用Numpy和python内置random库进行不同实现效率的底层差异的一个浅薄了解。
Pt1. 蒙特卡罗算法
蒙特卡罗算法是一种基于随机抽样的数值计算方法,核心就是使用“随机性”解决“确定性”的问题。
这种算法的一种典型表现形式是:所求解问题可以转化为某种随机分布的特征数^ ,举一个很直观的例子就是:求π的近似值。
在直角坐标系中,以原点为圆心,做单位圆,同时做它的外切正方形,之后我们可以进行N次随机实验,根据大数定律^ ,当N足够大时:落在圆内的点数/总点数 = 圆面积/正方形面积。

比较搞笑的是,这张图片是使用matplotlib绘制的,绘制1亿个数据点直接卡死了,这是1百万的样子。
Pt2. 实现
编码
使用time.time()
观察输出时间
import timeimport numpy as npimport random
#1亿次n = 100_000_000
start_np = time.time()
points = np.random.uniform(-1, 1, size=(n, 2))distance_squared = np.sum(points**2, axis=1)inside = np.sum(distance_squared <= 1)pi_numpy = 4 * inside / n
end_np = time.time()
time_np = end_np - start_np
#重置insideinside = 0
start_random = time.time()
for _ in range(n): x = random.uniform(-1, 1) y = random.uniform(-1, 1) if x**2 + y**2 <= 1: inside += 1pi_random = 4 * inside / n
end_random = time.time()time_random = end_random - start_random
print(f"Numpy计算结果: {pi_numpy:.10f}, 时间: {time_np:.2f}秒")print(f"random计算结果: {pi_random:.10f}, 时间: {time_random:.2f}秒")
结果
第一次
Numpy计算结果: 3.1416472400, 时间: 4.96秒random计算结果: 3.1413288800, 时间: 49.20秒
第二次
Numpy计算结果: 3.1415549200, 时间: 3.58秒random计算结果: 3.1418608000, 时间: 50.51秒
每一次运行结果不一样(伪随机数生成),还有一个很明显的区别在于运行时间上。差的很多。
Pt3. 原因分析
使用random库方案时间开销主要在for循环上,python本身的动态特性加上随机数生成器的时间再加上for循环本身边界检查,类型推断等的时间就让这种方案实现蒙特卡罗算法自然是不低了。
Numpy底层使用C实现,使用SIMD指令^一次性处理整个数组,CPU在单条指令中并行计算所有点的平方和,在实验结果上表明,还是Numpy在大数处理上占优势,更能发挥硬件的性能。