2014-03-31 30 views
6

我有一个python函数从文本文件读取一行并将其写入另一个文本文件。它为文件中的每一行重复此操作。基本上:并行I/O - 为什么它可以工作?

Read line 1 -> Write line 1 -> Read line 2 -> Write line 2... 

等等。

我可以parallelise这个过程中,使用队列来传递数据,因此它更像是:

Read line 1 -> Read line 2 -> Read line 3... 

       Write line 1 -> Write line 2.... 

我的问题是 - 为什么这项工作(如为什么我得到一个加速?) 。听起来像一个愚蠢的问题,但我想 - 我的硬盘当然只能一次做一件事?那么为什么没有一个过程搁置直到另一个过程完成?

这样的事情在用高级语言编写时对用户是隐藏的。我想知道低级别的事情是怎么回事?

回答

7

总之:IO缓冲。它的两个级别,甚至。

首先,Python本身具有IO缓冲区。因此,当您将所有这些行写入文件时,Python不一定会立即调用系统调用 - 它会在刷新其缓冲区时执行此操作,这可能是从调用write直到关闭文件的任何时候。这显然不会影响你,如果你写在你自己进行系统调用的级别。

但是与此分开,操作系统将执行缓冲区。这些工作方式相同 - 您将“写入磁盘”系统调用,操作系统将数据放入其写入缓冲区,并在其他进程读取该文件时使用该缓冲区。但它不一定会将其写入磁盘 - 理论上它可以等待直到卸载该文件系统(可能在关闭时)。这是(一部分)为什么拔下USB存储设备而不卸载或“安全删除”它不是个好主意 - 例如,您写入的内容在设备上不一定是物理。操作系统所做的任何操作都不受你正在编写什么语言,或者你有多少系统调用包装。

除此之外,Python和操作系统都可以读取缓冲 - 实际上,当您从文件中读取一行时,Python /操作系统预计您可能对接下来的几行也感兴趣,所以将它们读入主存储器以避免以后必须一直延迟到磁盘本身。

+0

一个很好的描述,谢谢。我想知道是否有我们可以实现的技术(用python)来控制它,以及是否控制它可以让我们进一步提高性能? – jramm

+2

@jramm来自Python,'open'采用可选的'buffering'参数。 0表示关闭缓冲,1表示缓冲区在每次写入换行符时被刷新(行缓存),其他正整数是以字节为单位的缓冲区大小;负值使用默认值。 Python 2和Python 3之间的默认设置发生了变化 - Python 2文档称它通常是完全缓冲的(缓冲区大小是文件大小)或行缓冲,取决于文件的类型;在Python 3中,它是为ttys进行行缓冲的,否则就是启发式。默认值通常已经很好的调整了,这就是它默认的原因。 – lvc

+0

不过,您不能AFAIK通常更改操作系统缓冲策略。或者说,他们提出的任何调整可能都是特权操作。但是,再次,默认值通常是它们的原因,因为广泛的测试发现它们适用于大多数常见情况。 – lvc

相关问题