Numpy中数组除法的性能优化探究
数组除法转乘法的性能优化问题
一、除数为数组的场景
原始实现
import numpy as np a = np.random.uniform(-1, 1, size=(1000000,)) b = np.random.uniform(-1, 1, size=(1000000,)) c = np.random.uniform(-1, 1, size=(1000000,)) d = np.random.uniform(1, 100, size=(1000000,)) a1 = a / d b1 = b / d c1 = c / d
优化写法(转乘法)
d_recip = 1 / d a1 = a * d_recip b1 = b * d_recip c1 = c * d_recip
Numpy底层优化情况
Numpy没有自动针对这种多数组除以同一数组的场景做优化。每次a/d、b/d都是独立运算,Numpy无法感知到重复使用同一除数数组,因此会每次执行除法操作。由于除法的硬件指令延迟远高于乘法,提前计算倒数再执行三次乘法的总耗时会更低——仅需一次除法(计算d_recip)加三次乘法,整体运算延迟显著减少。
Cython中的优化情况
Cython默认不会自动将多次除法转换为“倒数+乘法”逻辑,但如果你手动写出d_recip = 1/d再执行乘法,开启编译优化(如-O3)后,会和原生C代码一样利用CPU指令集优化,这种写法的性能优势与原生C表现一致,比多次除法更快。
二、除数为标量的场景
代码示例
import numpy as np a = np.random.uniform(-1, 1, size=(1000000,)) b = np.random.uniform(-1, 1, size=(1000000,)) c = np.random.uniform(-1, 1, size=(1000000,)) d = 1.65 # 写法1:直接除法 a1 = a / d b1 = b / d c1 = c / d # 写法2:转乘法 d_recip = 1 / d a2 = a * d_recip b2 = b * d_recip c2 = c * d_recip
性能表现
Numpy已经针对标量除法做了底层优化:执行a / d(d为标量)时,Numpy内部会自动计算标量的倒数,再执行数组与倒数的乘法操作,因此两种写法的性能几乎无差异。手动转乘法的方式不会比直接除法更快,因为Numpy已完成该优化。
注:已知倒数计算会导致比特级结果不一致,此回答仅针对不要求精确比特匹配的性能优化场景。
内容的提问来源于stack exchange,提问作者Rob Allsopp
相关产品推荐
相关产品推荐

