简体   繁体   English

为什么IDLE 3.4在这个程序上需要这么长时间?

[英]Why does IDLE 3.4 take so long on this program?

EDIT: I'm redoing the question entirely. 编辑:我完全重做了这个问题。 The issue has nothing to do with time.time() 这个问题与time.time()无关

Here's a program: 这是一个程序:

import time
start=time.time()
a=9<<(1<<26)             # The line that makes it take a while
print(time.time()-start)

This program, when saved as a file and run with IDLE in Python 3.4, takes about 10 seconds, even though 0.0 is printed out from time.time() . 当程序保存为文件并在Python 3.4中使用IDLE运行时,大约需要10秒,即使从time.time()打印出0.0。 The issue is very clearly with IDLE, because when run from the command line this program takes almost no time at all. IDLE非常清楚这个问题,因为从命令行运行时,这个程序几乎没有时间。

Another program that has the same effect, as found by senshin, is: 另一个具有相同效果的程序,如senshin所发现的,是:

def f(): 
    a = 9<<(1<<26)

I have confirmed that this same program, when run in Python 2.7 IDLE or from the command line on python 2.7 or 3.4, is near instantaneous. 我已经确认,当在Python 2.7 IDLE或python 2.7或3.4上的命令行中运行时,这个程序几乎是即时的。

So what is Python 3.4 IDLE doing that makes it take so long? 那么什么是Python 3.4 IDLE这样做需要这么长时间? I understand that calculating this number and saving it to memory is disk intensive, but what I'd like to know is why Python 3.4 IDLE performs this computation and write when Python 2.7 IDLE and command line Python presumably do not. 我知道计算这个数字并将其保存到内存是磁盘密集型的,但我想知道的是为什么Python 3.4 IDLE执行此计算并在Python 2.7 IDLE和命令行Python可能不会执行时编写。

I would look at that line and pick it apart. 我会看那条线并把它拆开。 You have: 你有:

9 << (1 << 26)

(1 << 26) is the first expression evaluated, and it produces a really large number. (1 << 26)是第一个被评估的表达式,它产生了一个非常大的数字。 What this line is saying, is that you are going to multiply the number 1 by 2 to the power of 26, effectively producing the number 2 ** 26 in memory. 这句话的意思是,你要将数字1加2乘以26的幂,有效地产生2 ** 26的内存。 This is not the problem however. 然而,这不是问题。 You then shift 9 left by the count of 2 ** 26. This produces a number that is around 50 million digits long in memory (I cant even calculate it exactly!), because the shift left is just too big. 然后你将9向左移动2 ** 26.这会在内存中产生一个大约5000万位数的数字(我甚至无法计算它!),因为左移是太大了。 Be careful in the future, as shifts by what seems to be small amounts do in fact grow very fast. 将来要小心,因为看起来很小的变化实际上会变得非常快。 If it was any larger, your program may have not run at all. 如果它更大,你的程序可能根本没有运行。 Your expression mathematically evaluates to 9 * 2 ** (2 ** 26) , if you were curious. 如果你很好奇,你的表达式在数学上的计算结果为9 * 2 ** (2 ** 26)

The ambiguity in the comment section is probably actually dealing with how this huge portion of memory is handled by python under the hood, and not IDLE. 注释部分中的含糊不清可能实际上是关于如何通过引擎盖下的python处理这个巨大的内存部分,而不是IDLE。

EDIT 1: 编辑1:

I thing that what is happening, is that a mathematical expression evaluates to its answer, even when placed inside of a function that isn't called yet, only if the expression is self sufficient . 我知道发生了什么,即使表达式是自给自足的 ,数学表达式也会评估它的答案,即使它被放置在一个尚未被调用的函数内部。 This means that if a variable is used in the equation, the equation will be untouched in the byte code, and not evaluated until hard execution. 这意味着如果在等式中使用变量,则等式将在字节代码中不受影响,并且在硬执行之前不进行评估。 The function has to be interpreted, and in that process, I think that your value is actually computed, resulting in the slower times. 必须解释该函数,并且在该过程中,我认为您的值实际上是计算的,导致较慢的时间。 I am not sure about this, but I strongly suspect this behavior to be the root cause. 我不确定这一点,但我强烈怀疑这种行为是根本原因。 Even if it is not so, you got to admit that 9<<(1<<26) kicks the computer in the behind, there's not much optimization that can be done there. 即使不是这样,你必须承认9<<(1<<26)将计算机踢在后面,没有太多的优化可以在那里完成。

In[73]: def create_number():
            return 9<<(1<<26)
In[74]: #Note that this seems instantaneous, but try calling the function!
In[75]: %timeit create_number()
#Python environment crashes because task is too hard

There is a slight deception in this kind of testing however. 然而,在这种测试中存在轻微的欺骗。 When trying this with the regular timeit, I got: 当我用常规时间尝试这个时,我得到了:

In[3]: from timeit import timeit
In[4]: timeit(setup = 'from __main__ import create_number', stmt = 'create_number()', number = 1)
Out[4]: .004942887388800443

Also keep in mind that printing the value is not do-able, so something like: 还要记住,打印值是不可行的,所以类似于:

In[102]: 9<<(1<<26)

should not even be attempted. 甚至不应该尝试。

For even more added support: 为了获得更多支持:

I felt like a rebel, so I decided to see what would happen if I timeit the raw execution of the equation: 我觉得自己像个反叛者,所以我决定看看如果我计算等式的原始执行时会发生什么:

In[107]: %timeit 9<<(1<<26)
10000000 loops, best of 3: 22.8 ns per loop

In[108]: def empty(): pass
In[109]: %timeit empty()
10000000 loops, best of 3: 96.3 ns per loop

This is really fishy, because apparently this calculation happens faster than the time it takes Python to call an empty function, which is obviously not the case. 这真的很可疑,因为显然这个计算发生的速度比Python调用空函数的时间要快,显然情况并非如此。 I repeat, this is not instantaneous, but probably has something to do with retrieving an already calculated object somewhere in memory, and reusing that value to calculate the expression. 我再说一遍,这不是即时的,但可能与在内存中某处检索已计算的对象并重用该值来计算表达式有关。 Anyways, nice question. 无论如何,好问题。

I am really puzzled. 我真的很困惑。 Here are more results with 3.4.1. 以下是3.4.1的更多结果。 Running either of the first two lines from the editor in either 3.4.1 or 3.3.5 gives the same contrast. 从3.4.1或3.3.5中的编辑器运行前两行中的任何一行都会产生相同的对比度。

>>> a = 1 << 26; b = 9 << a  # fast, , .5 sec
>>> c = 9 << (1 << 26)  # slow, about 3 sec
>>> b == c  # fast
True
>>> exec('d=9<<(1<<26)', globals())  # fast
>>> c == d  # fast
True

The difference between normal execution and Idle's is that Idle exec's code in an exec call like the above, except that the 'globals' passed to exec is not globals() but a dict configured to look like globals(). 正常执行和Idle之间的区别在于,在exec调用中空闲exec的代码如上所述,除了传递给exec的'globals'不是globals()而是配置为看起来像globals()的dict。 I do not know of any 2.7 -- 3.4 difference in Idle in this respect except for the change of exec from statement to function. 在这方面我不知道任何2.7 - 3.4的空闲差异,除了执行人员从执行到执行的变更。 How can exec'ing an exec be faster than a single exec? 如何执行一个exec比一个exec更快? How can adding an intermediate binding be faster? 如何更快地添加中间绑定?

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

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