优化Python中的for循环
我有一个循环,它在某个功能中占用了我最多的时间,我想加快它的速度。目前,这个单独的循环大约需要400毫秒,而整个函数的执行时间大约是610毫秒。
代码如下:
for ctr in xrange(N):
list1[ctr] = in1[ctr] - in1[0] - ctr * c1
list2[ctr] = in2[ctr] - in2[0] - ctr * c2
list3[ctr] = c3 - in1[ctr]
list4[ctr] = c4 - in2[ctr]
N的值大约在40,000到120,000之间,代表所有列表(in1、in2、listN)的长度。
有没有人知道一些可以加速这个过程的Python技巧?我已经尝试过使用map,因为我知道它会尝试编译成更高效的代码,但结果反而慢了大约250毫秒。
谢谢!
相关问题:
9 个回答
1
优化的效果取决于编译器,但你可以尝试一些方法。很高兴看到你在对代码进行性能分析!
你可以试试:
先把
in1[ctr]和其他经常用到的表达式存储到一个变量里(虽然大多数编译器已经能做到这一点,但谁知道呢)。进行循环分裂(可以参考这个链接:http://en.wikipedia.org/wiki/Loop_fission),如果你在处理大数组时遇到缓存问题的话。
2
最开始的时候我犯了个小错误(见下文),这些东西其实应该更好地进行缓存。
# These can be cached as they do not change.
base_in1 = in1[0]
base_in2 = in2[0]
for ctr in xrange(N):
# these are being looked up several times. Look-ups take time in almost every
# language. Look them up once and then use the new value.
cin1 = in1[ctr]
cin2 = in2[ctr]
list1[ctr] = cin1 - base_in1 - ctr * c1
list2[ctr] = cin2 - base_in2 - ctr * c2
list3[ctr] = c3 - cin1
list4[ctr] = c4 - cin2
(下面是错误的地方):
我最开始以为可以通过缓存常量来解决这个问题:
# these values never change
ctr1 = ctr * c1
ctr2 = ctr * c2
in10 = ctr1 + in1[0]
in20 = ctr2 + in2[0]
for ctr in xrange(N):
# these are being looked up several times. That costs time.
# look them up once and then use the new value.
cin1 = in1[ctr]
cin2 = in2[ctr]
list1[ctr] = cin1 - in10
list2[ctr] = cin2 - in20
list3[ctr] = c3 - cin1
list4[ctr] = c4 - cin2
但正如Tim指出的,我在最初的尝试中漏掉了ctr。
9
假设你的 list1、list2 等都是数字类型的,建议使用 numpy 数组来代替普通的列表。对于大量的整数或浮点数,你会发现速度提升非常明显。
如果你选择这个方法,你上面的循环可以这样写:
ctr = np.arange(N)
list1 = n1 - n1[0] - ctr * c1
list2 = n2 - n2[0] - ctr * c2
list3 = c3 - ctr
list4 = c4 - ctr
另外,这里有一个完整的独立示例,用来测试时间:
import numpy as np
N = 100000
# Generate some random data...
n1 = np.random.random(N)
n2 = np.random.random(N)
c1, c2, c3, c4 = np.random.random(4)
ctr = np.arange(N)
list1 = n1 - n1[0] - ctr * c1
list2 = n2 - n2[0] - ctr * c2
list3 = c3 - ctr
list4 = c4 - ctr
当然,如果你的 list1、list2 等不是数字(也就是说,它们是其他类型的 Python 对象,而不是浮点数或整数),那么这个方法就没什么帮助了。