为什么在 PyPy 中根据用户输入构建列表并打印其内容比 CPython 慢得多?

Why is building a list from user input and printing its contents much slower in PyPy than CPython?

我在 CodeForces 中编写一个问题,我 submitted 在 PyPy 中将此代码 运行:

import math
a=[]
b=[]
t=int(input())
for i in range(t):
    n=float(input())
    a.append(math.floor(n))
    b.append(math.ceil(n))
l=0-sum(a)
i=0
while i<len(a):
    if l>0 and a[i]!=b[i]:
        print(b[i])
        l-=1
    else:
        print(a[i])
    i+=1

然而,我得到了 "time limit exceeded" 的判决,执行时间超过 1 秒。

CPython 解释器 运行 时的相同代码 ran in under 600 ms

据我了解,PyPy 通常比 Python 快。为什么 CPython 对于此代码会更快?

欢迎来到 Stack Overflow!简而言之,在这种情况下 PyPy 输给 CPython 的原因是我们 运行 的 Python 代码并没有真正计算太多,而是所有的时间都花在做 input/output(首先是 input() 的循环,然后是 print() 的循环)。这可能是花费时间的主要部分。 PyPy 的 input/output 例程没有 CPython 的例程优化得好,这就是为什么它有点慢的原因。当您编写的 Python 代码花费时间在 Python.

中进行计算时,您可以猜测 PyPy 将战胜 CPython,有时是巨大的

"doing computations in Python" 的对立面有时称为 "running library code"---这包括 input/output 之类的东西,或者更一般地说,单个 Python 函数调用调用相当多的东西很多C代码。请注意,counter-intuitively,这还包括对非常非常大的整数进行算术运算,因为这需要为每个单独的操作编写大量 C 代码。相反的极端例子是对 "small" 个整数进行算术运算,直到 sys.maxsize,因为 PyPy JIT 可以将每个操作直接映射到一个 CPU 指令。

总而言之,PyPy 在 一些 纯 Python--- 不一定 所有 时间花费的地方是好的时间。例如,non-trivial pure-Python web 服务器往往从 PyPy 中获益良多:原始套接字 input/output 确实有点慢,但是处理查询和构建响应的所有逻辑都很多更快,这很容易成为执行时间的主要部分。