在Python中使用列表方法加速循环
我在python中使用了for循环,它迭代了将近250万次,并且需要花费大量时间才能得到结果。在JS中,我可以在将近1秒的时间内实现这一点,但Python在我的计算机上只需6秒。在这种情况下,我必须使用Python。代码如下:在Python中使用列表方法加速循环,python,list,for-loop,iteration,Python,List,For Loop,Iteration,我在python中使用了for循环,它迭代了将近250万次,并且需要花费大量时间才能得到结果。在JS中,我可以在将近1秒的时间内实现这一点,但Python在我的计算机上只需6秒。在这种情况下,我必须使用Python。代码如下: for i in xrange(k,p,2): arx = process[i] ary = process[i+1] for j in xrange(
for i in xrange(k,p,2):
arx = process[i]
ary = process[i+1]
for j in xrange(7,-1,-1):
nx = arx + dirf[j]
ny = ary + dirg[j]
ind = ny*w+nx
if data[ind] == e[j]:
process[c]=nx
c=c+1
process[c]=ny
c=c+1
matrix[ind]=1
以下是代码中的一些列表:
process=[None]*(11000*4)
赋值后,它的项将替换为整数
dirf = [-1,0,1,-1,1,-1,0,1]
dirg = [1,1,1,0,0,-1,-1,-1]
e = [9, 8, 7, 6, 4, 3, 2, 1]
数据列表由rgba图像像素的“r”信息组成。
data=imgobj.getdata(0)
我怎样才能提高这一点。我做错了什么?关于循环还有其他方法吗?谢谢。以下是一些改进代码的建议: 内部xrange被大量使用:如果您将其作为一个常规列表并执行类似操作,会怎么样:
inner = range(7,-1,-1) # make the actual list
for(a,b,c): #first for
#stuff
for i in inner # reference an actual list and not the generator
证据:
n = range(7,-1,-1)
def one():
z = 0
for k in xrange(100):
for i in n:
z+=1
def two():
z = 0
for k in xrange(100):
for i in xrange(7,-1,-1):
z+=1
if __name__ == '__main__':
import timeit
print("one:")
print(timeit.timeit("one()",number=1000000 ,setup="from __main__ import one"))
print("two:")
print(timeit.timeit("two()",number=1000000 ,setup="from __main__ import two"))
"result"
one:
37.798637867
two:
63.5098838806
如果我编写的代码具有可比性,那么它似乎表明引用内部列表而不生成确实加快了速度。
[编辑]引用局部变量比访问全局变量快。
因此,如果这是正确的,请将列表定义放置在尽可能靠近循环的位置,而不必每次都生成它
您还将更改流程两次。如果不需要,就选一个
正如你在评论中提到的,你说你正在处理图像。我不确定以下内容是否相关,但也许您可以使用openCV,它有一个Python API到C代码。那可能会加快速度。正如其他人提到的:numpy和您自己的cython扩展将大大加快这一速度。以下是一些改进代码的建议: 内部xrange被大量使用:如果您将其作为一个常规列表并执行类似操作,会怎么样:
inner = range(7,-1,-1) # make the actual list
for(a,b,c): #first for
#stuff
for i in inner # reference an actual list and not the generator
证据:
n = range(7,-1,-1)
def one():
z = 0
for k in xrange(100):
for i in n:
z+=1
def two():
z = 0
for k in xrange(100):
for i in xrange(7,-1,-1):
z+=1
if __name__ == '__main__':
import timeit
print("one:")
print(timeit.timeit("one()",number=1000000 ,setup="from __main__ import one"))
print("two:")
print(timeit.timeit("two()",number=1000000 ,setup="from __main__ import two"))
"result"
one:
37.798637867
two:
63.5098838806
如果我编写的代码具有可比性,那么它似乎表明引用内部列表而不生成确实加快了速度。
[编辑]引用局部变量比访问全局变量快。
因此,如果这是正确的,请将列表定义放置在尽可能靠近循环的位置,而不必每次都生成它
您还将更改流程两次。如果不需要,就选一个
正如你在评论中提到的,你说你正在处理图像。我不确定以下内容是否相关,但也许您可以使用openCV,它有一个Python API到C代码。那可能会加快速度。正如其他人所提到的:numpy和您自己的cython扩展将大大加快速度。在我的机器上迭代250万次需要34.9毫秒(速度很慢,但不是6秒慢)。如果您必须使用它们;你应该问问他们:他们是干什么的?目的何在?这里有一个很好的入门参考:像numba、numerical python()或cython()这样的库将为您提供一些提高性能的选项您计时的方式可能会扭曲事情-在前后花费
时间。时间()
和减法不是最佳实践;相反,使用模块对整个脚本计时,并使用获取有关是什么使其减速的详细信息。我不能很好地理解你的巴斯丁代码是怎么做的,但是它看起来像是一个很好的选择——速度和可读性都可以。而且,考虑到性能问题和在其他工作代码中的一般最佳实践的问题可能会被更好地提出。在我的机器上迭代250万次需要34.9毫秒。(很慢,但不是6秒慢)。如果你必须使用它们,你应该询问它们:它们做什么?目的是什么?这里有一个很好的入门参考:像numba、numerical python()或cython()之类的库将为您提供一些提高性能的选项您计时的方式可能会扭曲事情-占用时间。时间()之前和之后,减法并不是最佳实践;相反,使用模块来对整个脚本进行计时,并使用它来获取关于减慢其速度的详细信息。我不能很好地理解您的巴斯丁代码所做的事情,但它看起来像NUMPY是一个很好的选择——既考虑速度又可读性。也考虑这个问题。关于性能问题和其他工作代码中的一般最佳实践的ons可能会被更好地询问。您的任务计时集不会显示十分之一秒的加速-最后的e-08
意味着差异实际上大约是一纳秒。您不调用xrange
的计时大约在e循环的加速比为(63.5-37.8)/100000秒。即使在一个关键的内循环中,这些类型的微优化对整个运行时间的影响也可能是微不足道的。是的,我同意,我忘了读取指数,这将删除该部分。但是,从a)开始,您在其中留下的位几乎同样糟糕您没有平均通过次数的计时,并且b)您测试的更改只影响一次整个外循环。即使OPs外部循环的迭代次数比您的示例要多,您已经提供了证据,证明它们最多可以节省,从6秒的运行时间中减去几毫秒。您的一组作业计时没有显示十分之一秒的加速,这意味着最后的e-08
意味着差异实际上大约是一纳秒。您每次在循环中不调用xrange
的计时会产生(63.5-37.8)/100000秒的加速,这是非常重要的。即使在一个关键的内部循环中,这些类型的微优化可能对整个运行时间的影响微乎其微。是的,我同意,我忘了读指数,这将删除该部分。您留下的位几乎同样糟糕,尽管,因为a)您没有平均通过次数的计时,b)测试所针对的更改会影响整个外部循环一次。即使OPs外部循环的迭代次数比您的示例多得多,您已经提供了证据,证明它们可能会在版本中保存