我问这个问题是因为当使用重复的print语句调试循环时,它会使程序的运行速度降低到我原本预期的程度。我已经习惯了这个,但现在我很好奇为什么会出现这种情况的技术原因?在我看来,变量的各种计算和分配比输出字符串更昂贵。
答案 0 :(得分:6)
相当多,但另一个重要(甚至是最重要的)瓶颈与CPU无关:I / O开销。一旦调度了字节码指令并且所有参数都已转换为字符串,就会调用一个函数将这些字符串写入sys.stdout
。根据您的系统和运行程序的方式,这可能是:
在#1的情况下,涉及磁盘I / O,这比写入RAM要容易一个数量级。与今天的CPU相比,RAM已经非常慢了。正如评论中所指出的那样,由于操作系统和Python的广泛缓冲,这不是一个问题,但仍然需要时间来发出写入(并且(取决于我不太了解的实现细节)它可能仍需要一些如果有人过早冲洗任何缓冲区的时间。
在#2的情况下,一切都保留在内存中,但它仍然是一个系统调用,一些复制,另一端必须读取它并做一些事情让你注意到(例如在一个花哨的终端模拟器中渲染它一种消除锯齿的字体,这本身就是一项复杂的任务)。它不是一个问题,因为它可以同时发生,但它仍然会加载CPU。
在#3的情况下,所有投注均已关闭。它可以使用bcrypt对输出进行散列并将其发送到月球,我们所知道。你碰巧使用IDLE吗?我记得有一个抱怨,说IDLE是(<?> 非常慢,重定向输出,特别是有很多尖齿片。它必须捕获输出,到目前为止将它与输出连接起来,然后让Tkinter渲染它。
答案 1 :(得分:2)
巨大的,巨大的, 巨大的 数字,特别是如果输出在屏幕上可见,例如在现代多任务系统的终端仿真器窗口中。
首先,如果您输出的是十进制数字,则每个数字都有一个divmod,与添加相比,这是一个相对昂贵的操作。 (如果以十六进制输出,它可能会更便宜一些,因为每个数字只能使用移位和屏蔽来提取。)如果输出浮点数,则需要进行更多计算;有了日期和时间,有几个月的各种长度,闰年,闰秒,夏令时和时区都需要考虑。
但这只是计算和逻辑,所以它与即将发生的事情相形见绌。
接下来Python必须将输出文本发送到终端进行显示,这意味着操作系统必须介入以通过缓冲区传输数据,然后唤醒其他进程。终端进程扫描其输入以获取控制序列以移动光标或更改颜色。然后文本渲染器扫描文本中需要特殊处理的字符:可能需要应用一些组合重音,或者需要重新排列以显示的一些从右到左的脚本。
一旦布置了文本,终端就告诉窗口管理器需要重绘其窗口的哪个区域,窗口管理器检查它是否可见 - 它可能被最小化或隐藏在另一个窗口后面。终端被告知哪个区域实际上需要绘画,最后以正确的字体和颜色绘制文本,进行字距调整和抗锯齿处理。窗户的背景是否看起来很酷?这也必须合并。
根据窗口系统的不同,像素可以继续通过操作系统缓冲区到达合成管理器,实际上将窗口内容绘制到屏幕上,同时考虑窗口透明度。
最后,像素到达屏幕,在他们被数百万接班人一扫而空之前几乎没有时间可见,因为你看输出流过得太快而无法阅读。
令人惊讶的是,我们的计算机为我们做了多少工作。
答案 2 :(得分:1)
这不是CPU指令的问题,至少不是Python程序中的CPU指令。当您使用终端仿真器(命令窗口)作为输出执行print
时,要打印的字符串将被复制到内核缓冲区中,然后再复制到终端进程的内存中。开销是在上下文切换(两个进程进行系统调用,即跳转到内核模式)和在内存中复制字符串。