简体   繁体   English

加快python中循环的求和

[英]Speeding up summation for loop in python

I have the following bottleneck and am wondering if anyone can suggest ways to speed it up. 我有以下瓶颈,想知道是否有人可以提出加速它的方法。

I have three lists x,y,z of length N . 我有三个长度为N列表x,y,z and I apply the following summation . 我应用以下总结

def abs_val_diff(x1, x2, x3, y1, y2, y3):
    """ Find the absolute value of the difference between x and y """
    return py.sqrt((x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0)

R = 0.1  
sumV = 0.0
for i in xrange(N):
    for j in xrange(i + 1, N):
        if R > abs_val_diff(x[i], y[i], z[i],
                            x[j], y[j], z[j]):
                sumV += 1.0

I have tried using numpy arrays, but either I am doing something wrong or there is a reduction in speed of about a factor of 2. 我尝试使用numpy数组,但是我做错了什么,或者速度降低了大约2倍。

Any ideas would be highly appreciated. 任何想法将不胜感激。

I believe you can utilize numpy a little more efficiently by doing something like the following. 我相信您可以通过执行以下操作来更有效地利用numpy。 Make a small modification to your function to use the numpy.sqrt: 对函数进行一些小的修改以使用numpy.sqrt:

import numpy as np

def abs_val_diff(x1, x2, x3, y1, y2, y3):
    """ Find the absolute value of the difference between x and y """
    return np.sqrt((x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0)

Then call with the full arrays: 然后使用完整数组调用:

res = abs_val_diff(x[:-1],y[:-1],z[:-1],x[1:],y[1:],z[1:])

Then, because you're adding 1 for each match, you can simply take the length of the array resulting from a query against the result: 然后,因为要为每个匹配项加1,所以您可以简单地将查询结果所得的数组长度作为结果:

sumV = len(res[R>res])

This lets numpy handle the iteration. 这让numpy处理迭代。 Hopefully that works for you 希望对你有用

Is there any reason you actually need to take the square root in your function? 您实际上是否需要在函数中取平方根? If all you do with the result is to compare it against a limit why not just square both sides of the comparison? 如果您要做的只是将结果与极限值进行比较,为什么不只是对比较的两边都做平方呢?

def abs_val_diff_squared(x1, x2, x3, y1, y2, y3):
    """ Find the square of the absolute value of the difference between x and y """
    return (x1 - y1) ** 2.0 + (x2 - y2) ** 2.0 + (x3 - y3) ** 2.0

R = 0.1
R_squared = R * R
sumV = 0.0
for i in xrange(N):
    for j in xrange(i + 1, N):
        if R_squared > abs_val_diff_squared(x[i], y[i], z[i],
                            x[j], y[j], z[j]):
                sumV += 1.0

I also feel there ought to be much bigger savings gained from sorting the data into something like an octtree so you only have to look at nearby points rather than comparing everything against everything, but that's outside my knowledge. 我还认为,将数据分类为八叉树之类的东西应该可以节省更多的钱,因此您只需要查看附近的点,而不是将所有内容与所有内容进行比较,但这是我所不知道的。

It turns out long, ugly, list comprehensions are generally faster than explicit loops in python because they can be compiled to more efficient bytecode. 事实证明,冗长,丑陋的列表推导通常比python中的显式循环快,因为它们可以被编译为更有效的字节码。 I'm not sure if it'll help for you, but try something like this: 我不确定是否对您有帮助,但是请尝试以下操作:

sumV = sum((1.0 for j in xrange(1+1, N) for i in xrange(N) if R > abs_val_diff(x[i], y[i], z[i], x[j], y[j], z[j])))

Yes, it looks absolutely atrocious, but there you go. 是的,它看起来绝对是残酷的,但是您去了。 More info can be found here and here . 更多信息可以在这里这里找到。

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

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