python 3中最快的标准输入/输出IO?

Posted

技术标签:

【中文标题】python 3中最快的标准输入/输出IO?【英文标题】:Fastest stdin/out IO in python 3? 【发布时间】:2011-12-20 09:29:12 【问题描述】:

我一直在使用 python 3.1.2 解决 SPOJ.pl 上的一些问题,一些人在简单问题上的快速结果让我想知道是否有更快的方法来处理输入和输出。

我尝试过使用

input()
print()

sys.stdin.readline()
sys.stdout.write()

或者说

for line in sys.stdin:
    #Handle input
    sys.stdout.write(output)

处理每一行。 我还尝试收集列表中的所有输出,并在处理完所有内容后立即打印。

但所有这些都会产生相似的执行时间。

有没有更快的方法来处理标准输入/输出的输入和输出?

【问题讨论】:

我认为,如果人们的结果比你快,原因不在你的 I/O 方面 这是我最初的猜测,但对于只需要将部分输入直接重定向到输出的问题也是如此。这就是我问这个问题的原因。 Python 3.1.2 不是用于性能测量的特别好的 Python 版本。 Python 3.2.2 是 Python 3 的最新版本,并且在这些版本之间进行了许多显着的性能改进。 【参考方案1】:

可能不会。

最后,print 将调用sys.stdout.write()。但由于print 是一个内置函数,可能用C 实现,它甚至可能比调用sys.stdout.write() 更快。

由于所有 IO 都必须通过 sys.stdout 返回的对象,这就是瓶颈。 sys.stdin 也是如此。

没有什么神奇的技巧可以让这个速度更快。

如果您需要更快的 IO,请尝试以下方法:

改为写入文件 使用缓冲 IO(在小型 shell 脚本中使用 buffer 命令管道标准输出)。 使用内存映射文件 确保读取您的输出的进程可以跟上。例如,DOS 控制台非常慢。如果您通过慢速命令管道输出,则可能会阻塞您的 python 进程。

[编辑] 似乎 SPOJ.pl 是某种程序员枪战网站。在这种情况下,I/O 速度不是罪魁祸首:您使用了错误的算法来解决问题。

良好性能和一般性能之间的速度差异很容易达到 10 到 100,000 倍。通过更改几行代码,我曾经可以让代码在不到 5 秒的时间内运行,而之前需要 45 分钟。

【讨论】:

谢谢,虽然我不能在 SPOJ.pl 上做任何这些,因为我提交了我的代码,然后它在他们的服务器上运行测试用例。让我感到困惑的是,人们的执行时间比我快得多,即使问题可以通过从输入中打印特定内容来解决。 @while:尝试用 C 语言编写您的解决方案,看看您是否可以匹配响应时间。我不知道SPOJ.pl 是如何计算运行时间的,但您可能需要支付 Python 解释器的费用来启动和字节编译您的 Python 脚本... 用 C 语言总是更快,但我正在与用 python 编写的其他解决方案进行比较。 嗯,这些问题的关键在于它们不能仅通过从输入中打印特定内容来解决,这就是人们获得更快执行时间的原因。【参考方案2】:

以下可能是最快的:

    使用os.read(0, some_big_enough_number)一次读取所有输入。

    处理输出,将结果收集到列表results

    使用os.write(1, "".join(results))一次写入所有输出。

我记得有一个案例,我注意到 os.read()os.write() 有时比使用 Python I/O 更快,但我不记得细节了。

【讨论】:

它并没有真正起作用,因为我不知道输入的长度。 @while:只要使用足够的数字,例如1000000000。它必须足以读取所有输入。 在我的机器(python 3.2.2)上测试时似乎稍快一些。虽然由于某种原因无法让它在 SPOJ (python 3.1.2) 上工作,但无论如何谢谢。 @while:这些主机限制进程可用的内存量并不少见。尝试阅读一些合理大小的块。无论如何,您最终将拥有更少的 I/O。【参考方案3】:

SPOJ 可让您在多种编程语言中进行选择。您是否将执行时间与用其他编程语言编写的其他解决方案进行比较?

为了好玩,我为第一个问题(代号TEST)提交了以下解决方案来比较运行时间。

C++ 解决方案(G++ 4.3.2)

#include <iostream>
int main ( int, char** )

     for ( int number=0; (std::cin >> number) && (number != 42); ) 
         std::cout << number << std::endl;
     

请参阅submission。

Python(2.5)解决方案

import sys
for line in sys.stdin:
    number = int(line)
    if number == 42:
        break
    print number

请参阅submission。

结论

我不能 100% 确定这会在两种语言中获得绝对最佳的性能,但其中没有太多需要优化的代码。

我得到时间 0.00 测量 C++ 和 0.04 测量 Python 代码。假设提交给两个程序的数字序列相同,我认为将运行时间与其他语言的解决方案进行比较几乎没有意义(见下一段)。

现在,这仅适用于简单问题。大多数高级问题都需要为问题选择正确的算法,而选择错误的算法会产生严重的后果。在这些情况下,精心设计的 Python 解决方案可能仍然比精心设计的 C++ 解决方案慢,但好的 Python 解决方案将胜过用任何其他语言编写的幼稚解决方案。

【讨论】:

谢谢,您说的完全正确,但我没有比较不同的语言。检查 python 3.1.2 中解决此问题的时间:spoj.pl/ranks/ACT/lang=PYTH%203.1.2 我所做的只是将输入重定向到输出,但我仍然得到 0.14,最快的是 0.02。这就是为什么我认为可能有一种更快的处理 io 的方法,这让我有点好奇。 那是因为实际程序的输出实际上很短,输入可能很长​​span>

以上是关于python 3中最快的标准输入/输出IO?的主要内容,如果未能解决你的问题,请参考以下文章

8_管理及IO重定向

文件IO详解---标准输入标准输出和标准错误

在 Python 中流式传输标准输入/标准输出

IO文件

Linux用户

Python中输入和输出(打印)数据