计算欧氏距离的Python优化

计算欧氏距离的Python优化,python,Python,这个函数在我的程序中运行了200多万次。有人能建议对此进行优化吗? 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])) 我的尝试:我尝试使用math.sqrt、pow和x**.5,但没有多少性能提升 您可以通过不访问同一个x[i]元素并在本地绑定它来减少一些周期 def distance(x,y): x0,

这个函数在我的程序中运行了200多万次。有人能建议对此进行优化吗? 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]))

我的尝试:我尝试使用math.sqrt、pow和x**.5,但没有多少性能提升

您可以通过不访问同一个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))
例如,比较:

>>> 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
与:


还有更多的

您可以通过不访问相同的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))
例如,比较:

>>> 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
与:

还有更多原创作品:

>>> 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
公共子表达式消除:

>>> 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
优化的拆包:

>>> 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
图书馆职能:

>>> 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
虚线:

>>> 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
原件:

>>> 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
公共子表达式消除:

>>> 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
优化的拆包:

>>> 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
图书馆职能:

>>> 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
虚线:

>>> 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具有欧几里得距离函数。你可能不会比这更快了


编辑:事实上,通过对OP的纯python距离函数运行timeit,这实际上在python浮动上要慢得多。我认为scipy版本会浪费一些时间将浮动转换为numpy数据类型。至少我很惊讶。

scipy有一个欧几里得距离函数。你可能不会比这更快了


编辑:事实上,通过对OP的纯python距离函数运行timeit,这实际上在python浮动上要慢得多。我认为scipy版本会浪费一些时间将浮动转换为numpy数据类型。至少可以说,我很惊讶。

最后一段距离你在干什么?如果你只是用它来比较,放下sqrt,把你要比较的东西平方。如果你懂C,我会用那种语言。众所周知,Python是一个效率低下的数学家。如果值x[i]-y[i]经常重复,您可以尝试缓存x[i]-y[i]*x[i]-y[i],您可能会对提供的工具感兴趣。@MarkRansom-这一点很好,但删除sqrt也没有多大帮助。超过200万次计算大约需要34秒,但对于同一个算法,论文作者使用具有类似硬件配置的Java在1秒内完成了计算。他的RAM:4GB,我的3GB,其他都是相同的。当我使用python时,这可能是语言的问题吗?你对最后的距离做了什么?如果你只是用它来比较,放下sqrt,把你要比较的东西平方。如果你懂C,我会用那种语言。众所周知,Python是一个效率低下的数学家。如果值x[i]-y[i]经常重复,您可以尝试缓存x[i]-y[i]*x[i]-y[i],您可能会对提供的工具感兴趣。@MarkRansom-这一点很好,但删除sqrt也没有多大帮助。超过200万次计算大约需要34秒,但对于同一个算法,论文作者使用具有类似硬件配置的Java在1秒内完成了计算。他的RAM:4GB,我的3GB,其他都是相同的。这可能是我使用python时的语言问题吗?您希望避免虚线表示法并从math导入sqrt,而不是调用math.sqrt并对每个调用产生惩罚。您希望避免虚线表示法并从math导入sqrt,而不是调用math.sqrt并对每个调用产生惩罚。