Python 为什么np.float32的执行速度可能比np.float64慢?
我正在根据POT的Python 为什么np.float32的执行速度可能比np.float64慢?,python,performance,numpy,linear-algebra,Python,Performance,Numpy,Linear Algebra,我正在根据POT的githubrepo的实现,为最优传输问题编写自己的Sinkhorn-Knopp算法实现。该函数如下所示: #version for the dense matrices def sinkhorn_knopp(C, reg, a = None, b = None, max_iter = 1e3, eps = 1e-9, log = False, verbose = False, log_interval = 10): a = np.asarray(a, dtype=np.fl
github
repo的实现,为最优传输问题编写自己的Sinkhorn-Knopp
算法实现。该函数如下所示:
#version for the dense matrices
def sinkhorn_knopp(C, reg, a = None, b = None, max_iter = 1e3, eps = 1e-9, log = False, verbose = False, log_interval = 10):
a = np.asarray(a, dtype=np.float64)
b = np.asarray(b, dtype=np.float64)
C = np.asarray(C, dtype=np.float64)
# if the weights are not specified, assign them uniformly
if len(a.shape) == 0:
a = np.ones((C.shape[0],), dtype=np.float64) / C.shape[0]
if len(b.shape) == 0:
b = np.ones((C.shape[1],), dtype=np.float64) / C.shape[1]
# Faster exponent
K = np.divide(C, -reg)
K = np.exp(K)
# Init data
dim_a = len(a)
dim_b = len(b)
# Set ininital values of u and v
u = np.ones(dim_a) / dim_a
v = np.ones(dim_b) / dim_b
r = np.empty_like(b)
Kp = (1 / a).reshape(-1, 1) * K
err = 1
cpt = 0
if log:
log = {'err' : []}
while(err > eps and cpt < max_iter):
uprev = u
vprev = v
KtransposeU = K.T @ u
v = np.divide(b, KtransposeU)
u = 1. / (Kp @ v)
if (np.any(KtransposeU == 0)
or np.any(np.isnan(u)) or np.any(np.isnan(v))
or np.any(np.isinf(u)) or np.any(np.isinf(v))):
# we have reached the machine precision
# come back to previous solution and quit loop
print('Warning: numerical errors at iteration', cpt)
u = uprev
v = vprev
break
if cpt % log_interval == 0:
#residual on the iteration
r = (u @ K) * v
# violation of marginal
err = np.linalg.norm(r - b)
if log:
log['err'].append(err)
cpt += 1
#return OT matrix
ot_matrix = u * K * v
loss = np.sum(C * ot_matrix)
if log:
return ot_matrix, loss, log
else:
return ot_matrix, loss
对于更大的问题,时间上的差异几乎是时间上的,这看起来相当奇怪。为什么会这样?您的计算机是否足够新,可以拥有64位总线和处理器?@hpaulj是的,确实如此。那么,为了使用$32$位算术计算某些东西,需要以某种方式将其转换为$64$位处理器,这样会产生额外的开销吗?奇怪的是,差距随着问题的大小而增大。对于较小的问题,差距没有较大的问题那么大。您是否检查了所有中间结果,以查看是否在后台进行了不需要的类型转换?但即使是这样,也可能有一些函数在执行任何操作之前将所有内容强制转换到float64内部。也许在这两个函数上运行探查器也可以提示这种行为的原因。您的计算机是否足够新,可以拥有64位总线和处理器?@hpaulj是的,就是这样。那么,为了使用$32$位算术计算某些东西,需要以某种方式将其转换为$64$位处理器,这样会产生额外的开销吗?奇怪的是,差距随着问题的大小而增大。对于较小的问题,差距没有较大的问题那么大。您是否检查了所有中间结果,以查看是否在后台进行了不需要的类型转换?但即使是这样,也可能有一些函数在执行任何操作之前将所有内容强制转换到float64内部。也许在这两个函数上运行探查器也可以提示这种行为的原因。
#np.float64 version
63.6 ms ± 7.94 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
#np.float32 version
71.4 ms ± 2.01 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
#np.float64 version
650 ms ± 12.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
#np.float32 version
2.48 s ± 298 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)