You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何PyPy处理用户输入构建列表并打印的速度慢于CPython?

Why CPython Outperforms PyPy in This Specific Code

这确实是个反直觉的情况——毕竟PyPy靠着JIT编译,大多时候比CPython快不少,但你的代码刚好踩中了PyPy的几个“软肋”,反而让CPython跑赢了:

1. JIT Warm-Up Overhead Kills Small/Fast Tasks

PyPy的核心优势是即时编译(JIT):它会在代码反复执行同一段逻辑时,把这段逻辑编译成机器码,后续执行就会快很多。但你的代码逻辑太简单了——循环里的操作无非是几个判断和输出,就算测试用例的t不小,整个程序的运行时间可能还没等PyPy完成JIT预热就结束了。反而CPython是纯解释执行,没有额外的编译预热成本,对付这种短平快的任务,直接跑反而更高效。

2. IO Operations Are a Bottleneck (And PyPy’s IO Isn’t Always Better)

你的代码有大量的input()和print()调用——这属于IO密集型操作。PyPy的标准库IO实现和CPython有差异,在频繁调用print()的场景下,PyPy的性能反而不如CPython。毕竟CPython的IO层经过了几十年的打磨优化,小批量多次输出的场景下,它的开销比PyPy更小。

3. Trivial Loops Don’t Benefit From JIT

你的主循环里的逻辑太简单了:只是判断两个条件,然后输出值。这种极其基础的循环,JIT编译器根本没机会发挥优势——编译这段简单代码的时间,甚至比直接解释执行它的时间还长。CPython处理这种简单循环的开销反而更低,自然跑得更快。

How to Make This Code Fast on PyPy?

如果想让PyPy发挥它的优势,重点是优化IO操作,减少频繁调用print()的开销:

  • 把所有输出先收集到一个列表里,最后一次性输出,这样能大幅减少IO系统调用的次数:
    import math
    import sys
    
    def main():
        data = sys.stdin.read().split()
        t = int(data[0])
        a = []
        b = []
        for s in data[1:t+1]:
            n = float(s)
            a.append(math.floor(n))
            b.append(math.ceil(n))
        
        l = -sum(a)
        output = []
        i = 0
        while i < len(a):
            if l > 0 and a[i] != b[i]:
                output.append(str(b[i]))
                l -= 1
            else:
                output.append(str(a[i]))
                i += 1
        
        print('\n'.join(output))
    
    if __name__ == "__main__":
        main()
    

这么改之后,不管是PyPy还是CPython都会更快,而且PyPy的JIT能更好地优化核心的循环逻辑,最终跑起来会比CPython还快。

另外,如果题目输入的数都是整数或者固定格式的小数,尽量避免用float()转换——用字符串处理或者直接转整数(如果符合题意)能进一步减少开销,但这得看题目具体要求。


内容的提问来源于stack exchange,提问作者Susanta Mukherjee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:53:51