本文介绍了为什么 IDLE 3.4 在这个程序上需要这么长时间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在完全重做这个问题.该问题与 time.time() 无关

I'm redoing the question entirely. The issue has nothing to do with time.time()

这是一个程序:

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

这个程序,当保存为文件并在 Python 3.4 中使用 IDLE 运行时,大约需要 10 秒,即使从 time.time() 打印出 0.0.IDLE 的问题非常明显,因为从命令行运行该程序几乎不需要任何时间.

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(). The issue is very clearly with IDLE, because when run from the command line this program takes almost no time at all.

senshin 发现的另一个具有相同效果的程序是:

Another program that has the same effect, as found by senshin, is:

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

我已经确认,在 Python 2.7 IDLE 中或从 Python 2.7 或 3.4 上的命令行运行时,相同的程序几乎是瞬时的.

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 3.4 IDLE 做了什么导致它需要这么长时间?我知道计算这个数字并将其保存到内存是磁盘密集型的,但我想知道的是为什么 Python 3.4 IDLE 执行此计算并在 Python 2.7 IDLE 和命令行 Python 可能不会执行此计算和写入.

So what is Python 3.4 IDLE doing that makes it take so long? 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.

推荐答案

我会看着那行并把它分开.你有:

I would look at that line and pick it apart. You have:

9 <<

(1 << 26) 是第一个计算的表达式,它产生一个非常大的数字.这一行的意思是,你将把数字 1 乘以 2 的 26 次方,从而在内存中有效地生成数字 2 ** 26.然而,这不是问题.然后将 9 左移 2 ** 26 的计数.这会在内存中产生一个大约 5000 万位数的数字(我什至无法准确计算它!),因为左移太大了.未来要小心,因为看似很小的变化实际上增长得非常快.如果它更大,则您的程序可能根本没有运行.如果您好奇,您的表达式在数学上的计算结果为 9 * 2 ** (2 ** 26).

(1 << 26) is the first expression evaluated, and it produces a really large number. 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. 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. 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.

评论部分的歧义可能实际上是在处理 Python 在后台如何处理这一巨大部分的内存,而不是 IDLE.

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.

编辑 1:

我认为正在发生的事情是,即使将数学表达式置于尚未调用的函数中,也可以对其求值,仅当表达式自给自足时.这意味着如果在方程中使用了一个变量,则该方程在字节码中将保持不变,并且在硬执行之前不会对其进行评估.该函数必须被解释,在这个过程中,我认为你的值实际上是计算出来的,导致时间变慢.我不确定这一点,但我强烈怀疑这种行为是根本原因.即使不是这样,你也必须承认 9< 把电脑踢到了后面,那里没有太多优化可以做.

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.

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:

输入[102]:9<

甚至不应该尝试.

更多支持:

我感觉自己像个反叛者,所以我决定看看如果我对等式的原始执行进行计时会发生什么:

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

这真的很可疑,因为显然这个计算发生得比 Python 调用空函数所需的时间更快,而这显然不是这种情况.我再说一遍,这不是即时的,但可能与检索内存中某处已经计算的对象有关,并重用该值来计算表达式.无论如何,好问题.

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. 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.

这篇关于为什么 IDLE 3.4 在这个程序上需要这么长时间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-26 15:24