而转换到发电机3.4倍减缓

怎么了? 有人可以给我解释一下这里发生的一切,我改变了紧密的循环:

## j=i ## while j < ls - 1 and len(wordlist[j]) > lc: j+=1 j = next(j for j in range(i,ls) if len(wordlist[j]) <= lc)

而版本跑了整个程序的注释:625毫秒下一台发电机版本运行整个程序中的2.125时候

有什么可以原因,这更Python版本导致性能这样的灾变?

编辑:也许这是由于使用的Psyco模块 ? 当然,至少在运行时间与Python 2.7里面有没有Psyco的,是2.141的下一个版本,意味着几乎相同的Python 2.6与Psyco的。

除去* pyc文件后,我得到了notthe代码放慢。 然后,当我删除从库模块Psyco的进口也,我得到了2.6的时序也可无Psyco的,结果非Psyco的版本和Psyco的版本(如现在的库函数减慢也和它的时机也有关:)

不使用Psyco:

  1. 同时:准备在图书馆:532毫秒,总运行时间2.625小号
  2. 下一个:准备在图书馆:532毫秒,总运行时间(time.clock()):2.844秒(版本的xrange同一面墙上的时间​​)

而Psyco:

  1. 同时:准备在图书馆:297毫秒,总运行时间:609..675毫秒
  2. 下一个:准备在图书馆:297毫秒,总运行时间:1.922秒(程序版本范围而不是到处的xrange:1.985 S)

运行在WindowsXP AMD闪龙3100+系统,2GB内存。 计数的循环和调用两个全局:

j=i callcount += 1 while j < ls - 1 and len(wordlist[j]) > lc: j+=1 loopcount += 1

结果为测试输入,而Psyco:

Finished in 625 ms Loopcount: 78317 Callcount: 47970 Ration: 1.633

因此,循环是内循环偏紧,但平均只执行了几次(注意,全局计数器两个增量并没有减缓的Psyco的代码)

结论:尽管相对该算法到词汇长度,这使我从这个循环中,以后递归基本病例是由字典查找检查哪个是O(n)来传递从考虑某些IMPOSIBLE词语的高度敏感性,因此, 高度有益较早优化变得不是很有利的,即使在更长的输入和移动在函数开头的callcount计数器,表明呼叫计数不会受词汇长度,但外循环计数slichtly减少(代码最初发布是在ELIF if语句的一部分)。

与while循环和全部循环移除(使用而不是J I)(文库制备312毫秒) 较长的运行时间(29 372解决方案):

  1. 如果没有循环:ELIF支数:485488,outerloopcount:10129147,比0048,6000运行S( 无柜台:4,594 S)
  2. 随着循环:loopcount:19355114,outercount:8194033,比0236,运行5704秒( 无柜台:4,688 S)

(运行时间不循环,计数器和使用Psyco:32792 S,库608毫秒)

因此,没有额外的计数器使用的Psyco这个循环的好处是在较硬的情况下:(4688-4594)* 100 / 4688.0%= 2%

这启发了我扭转早前的另一个优化 ,我曾在DaniWeb想知道。 代码运行的早期版本速度更快,最小字的大小是全球性的 ,而不是paramerter。 根据文件,局部变量调用速度更快,但apparantly成本作出递归重outweighted的。 现在在困难情况下,这等逆转优化话lenght没有优化的情况下,带来了更多的业绩预期的行为 :用Psyco的运行时间为312毫秒的准备,4,469..4,484总运行时间 。 所以这使得代码清洁器,在这种情况下,带来了更多的好处,因为在去除循环了。 而把参数版本while循环,并没有改变运行时间多(图书馆编制代码的变化变大)

**What I learned from this: If you do n optimizations for speed you must check the first n-1 optimizations after doing nth one**

--------------解决方案-------------

我发现,使用发电机往往比生成整个列表,这是一个有点反直觉的慢。 我已经成功地解决性能瓶颈只是通过添加[]对。

例如比较这些:

$ python -m timeit -n 1000 "' '.join(c for c in 'hello world')"
1000 loops, best of 3: 6.11 usec per loop
$ python -m timeit -n 1000 "' '.join([c for c in 'hello world'])"
1000 loops, best of 3: 3.79 usec per loop

这几乎两倍的快速生成整个列表第一,而不是使用一台发电机,即使对于这样一个简单的例子!

编辑:正如托马斯·沃特斯指出了意见的原因产生较慢这里因为它是这样一个简单的例子。 对于资产负债这里是他的测试,其中发电机是明显的赢家:

$ python -m timeit -s "s = 'hello world' * 10000" -s "class C: pass" "for i in (C() for c in s): pass"
10 loops, best of 3: 33.6 msec per loop
$ python -m timeit -s "s = 'hello world' * 10000" -s "class C: pass" "for i in [C() for c in s]: pass"
10 loops, best of 3: 172 msec per loop

两者是不等价的。

j=i
while j < ls - 1 and len(wordlist[j]) > lc:
j+=1

将尽快单词表[J] <= LC停止while循环。 它可以想见,通过在循环零倍如果在列表中的第一个字是短于或等于LC。

j = next(j for j in range(i,ls) if len(wordlist[j]) <= lc)

将继续通过整个范围i到ls的迭代而不管在列表中的字的长度,。

编辑 :忽略上面-琥珀指出的那样,调用next()是指发电机表达式只计算,直到第一个返回结果。 在这种情况下,我怀疑时差来自使用范围()代替的xrange()(除非这是Python的3​​.X)。 在Python 2.x的范围()将创建的完整列表在存储器中,即使在发电机表达式只返回的第一个值。

分类:蟒蛇 时间:2015-03-14 人气:0
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 0.590 (s). 10 q(s)