尝试通过用函数替换循环来加速python代码

时间:2014-01-03 01:27:00

标签: python performance function loops

我正在努力想出一种更快的方式来编码我想要的东西。这是我试图加速的程序的一部分,希望使用更多内置函数:

num = 0
num1 = 0
rand1 = rand_pos[0:10]
time1 = time.clock() 
for rand in rand1:   
     for gal in gal_pos:
         num1 = dist(gal, rand)
         num = num + num1 
time2 = time.clock()
time_elap = time2-time1
print time_elap

这里,rand_pos和gal_pos分别是长度为900和100万的列表。 这里dist是我计算欧几里德空间中两点之间距离的函数。 我使用rand_pos的片段来获得时间测量。 我的时间测量时间约为125秒。这太长了! 这意味着如果我在所有rand_pos上运行代码,则需要大约三个小时的时间! 我有更快的方法吗?

这是dist函数:

def dist(pos1,pos2):
    n = 0
    dist_x = pos1[0]-pos2[0]
    dist_y = pos1[1]-pos2[1]
    dist_z = pos1[2]-pos2[2]
    if dist_x<radius and dist_y<radius and dist_z<radius:
        positions = [pos1,pos2]
        distance = scipy.spatial.distance.pdist(positions, metric = 'euclidean')
        if distance<radius:
            n = 1       
return n

2 个答案:

答案 0 :(得分:3)

虽然大多数优化可能需要在dist函数中进行,但这里有一些提示可以加快速度:

# Don't manually sum
for rand in rand1:
    num += sum([dist(gal, rand) for gal in gal_pos])


#If you can vectorize something, then do
import numpy as np
new_dist = np.vectorize(dist)
for rand in rand1:
    num += np.sum(new_dist(gal_pos, rand))

# use already-built code whenever possible (as already suggested)
scipy.spatial.distance.cdist(gal, rand1, metric='euclidean')

答案 1 :(得分:2)

scipy中的某个功能完全符合您的要求:

scipy.spatial.distance.cdist(gal, rand1, metric='euclidean')

它可能比你在纯Python中编写的任何内容都快,因为繁重(在数组之间的成对组合上循环)是在C中实现的。

目前你的循环是在Python中发生的,这意味着每次迭代会有更多的开销,然后你会多次调用pdist。尽管pdist已经过优化,但是对它进行这么多调用的开销会降低代码的速度。这种类型的性能问题曾经用一个非常有用的类比描述给我:它就像试图通过电话与某人通过每个电话说一个单词进行对话,即使每个单词都快速通​​过电话,你的对话将需要很长时间,因为您需要重复挂断并再次拨号。