简体   繁体   English

Python优化用于计算欧氏距离

[英]Python Optimization For calculation of eucledian distance

This function is being run more than 2 million times in my program. 在我的程序中,此功能已运行超过200万次。 Can anyone suggest to optimize this? 有人可以建议对此进行优化吗? x and y are tuples. x和y是元组。

def distance(x,y):

    return sqrt((x[0]-y[0])*(x[0]-y[0])+(x[1]-y[1])*(x[1]-y[1])+(x[2]-y[2])*(x[2]-y[2]))

My try: I tried using math.sqrt, pow and x**.5 but there is not much performance gain. 我的尝试:我尝试使用math.sqrt,pow和x **。5,但性能提升不多。

you can shave off some cycles by not accessing same x[i] element and binding it locally. 您可以通过不访问相同的x [i]元素并将其本地绑定来节省一些周期。

def distance(x,y):
    x0, x1, x2 = x
    y0, y1, y2 = y
    return sqrt((x0-y0)*(x0-y0)+(x1-y1)*(x1-y1)+(x2-y2)*(x2-y2))

example, compare: 例如,比较:

>>> import timeit
>>> timer = timeit.Timer(setup='''
... from math import sqrt
... def distance(x,y):
...    return sqrt((x[0]-y[0])*(x[0]-y[0])+(x[1]-y[1])*(x[1]-y[1])+(x[2]-y[2])*(x[2]-y[2]))
... ''', stmt='distance((0,0,0), (1,2,3))')
>>> timer.timeit(1000000)
1.2761809825897217

with: 与:

>>> import timeit
>>> timer = timeit.Timer(setup='''
... from math import sqrt
... def distance(x,y):
...    x0, x1, x2 = x
...    y0, y1, y2 = y
...    return sqrt((x0-y0)*(x0-y0)+(x1-y1)*(x1-y1)+(x2-y2)*(x2-y2))
... ''', stmt='distance((0,0,0), (1,2,3))')
>>> timer.timeit(1000000)
0.8375771045684814

There are more performance tips on the python wiki. python Wiki上有更多性能提示。

Original: 原版的:

>>> timeit.timeit('distance2((0,1,2),(3,4,5))', '''
... from math import sqrt
... def distance2(x,y):
...     return sqrt((x[0]-y[0])*(x[0]-y[0])+(x[1]-y[1])*(x[1]-y[1])+(x[2]-y[2])*(x[2]-y[2]))
... ''')
1.1989610195159912

Common Subexpression Elimination: 常见子表达消除:

>>> timeit.timeit('distance((0,1,2),(3,4,5))', '''
... def distance(x,y):
...     d1 = x[0] - y[0]
...     d2 = x[1] - y[1]
...     d3 = x[2] - y[2]
...     return (d1 * d1 + d2 * d2 + d3 * d3) ** .5''')
0.93855404853820801

Optimized Unpacking: 优化的拆箱:

>>> timeit.timeit('distance((0,1,2),(3,4,5))', '''
... def distance(x,y):
...     x1, x2, x3 = x
...     y1, y2, y3 = y
...     d1 = x1 - y1
...     d2 = x2 - y2
...     d3 = x3 - y3
...     return (d1 * d1 + d2 * d2 + d3 * d3) ** .5''')
0.90851116180419922

Library Functions: 库功能:

>>> timeit.timeit('distance((0,1,2),(3,4,5))', '''
... import math
... def distance(x,y):
...     x1, x2, x3 = x
...     y1, y2, y3 = y
...     d1 = x1 - y1
...     d2 = x2 - y2
...     d3 = x3 - y3
...     return math.sqrt(d1 * d1 + d2 * d2 + d3 * d3)
... ''')
0.78318595886230469

Dotted: 点缀:

>>> timeit.timeit('distance((0,1,2),(3,4,5))', '''
... from math import sqrt
... def distance(x,y):
...     x1, x2, x3 = x
...     y1, y2, y3 = y
...     d1 = x1 - y1
...     d2 = x2 - y2
...     d3 = x3 - y3
...     return sqrt(d1 * d1 + d2 * d2 + d3 * d3)
... ''')
0.75629591941833496

scipy has a euclidian distance function. scipy具有欧氏距离功能。 You probably won't get any faster than that. 您可能不会比这更快。

http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.euclidean.html#scipy.spatial.distance.euclidean http://docs.scipy.org/doc/scipy/reference/generation/scipy.spatial.distance.euclidean.html#scipy.spatial.distance.euclidean

from scipy.spatial.distance import euclidean
import numpy as np

# x and y are 1 x 3 vectors
x = np.random.rand(1,3) 
y = np.random.rand(1,3)
euclidean(x,y)

EDIT: Actually, running this through timeit against OP's pure-python distance() function, this is actually turning out to be way slower on python floats. 编辑:实际上,通过针对OP的pure-python distance()函数的timeit运行此函数,实际上这在python float上的速度实际上要慢得多。 I think the scipy version wastes some time casting the floats to numpy dtypes. 我认为scipy版本浪费了一些时间将浮点数转换为numpy dtypes。 I'm quite surprised to say the least. 至少可以说我很惊讶。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM