并行I/O - 为什么它可以工作?

jra*_*amm 7 python io parallel-processing

我有一个python函数,它从文本文件中读取一行并将其写入另一个文本文件.它会对文件中的每一行重复此操作.实质上:

Read line 1 -> Write line 1 -> Read line 2 -> Write line 2...
Run Code Online (Sandbox Code Playgroud)

等等.

我可以使用队列来传递数据来并行化这个过程,所以它更像是:

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

              Write line 1 -> Write line 2....
Run Code Online (Sandbox Code Playgroud)

我的问题是 - 为什么这样做(因为我为什么加快速度?).听起来像是一个愚蠢的问题,但我在想 - 当然我的硬盘一次只能做一件事吗?那么为什么没有一个过程被搁置直到另一个过程完成?

当用高级语言写作时,这样的事情对用户是隐藏的.我想知道什么是低级别的?

lvc*_*lvc 8

简而言之:IO缓冲.它的两个层次,甚至.

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

但与此分开,操作系统将实现缓冲区.这些工作方式相同 - 您将'写入磁盘'系统调用,操作系统将数据放入其写入缓冲区,并在其他进程读取该文件时使用该数据.但它并不一定将其写入磁盘 - 理论上它可以等待,直到您卸载该文件系统(可能在关闭时).这是(部分),为什么它可以是一个坏主意,拔下USB存储设备,而无需卸载或"安全移除"它,例如-你写它不一定事情物理设备上呢.操作系统所做的任何事情都不会受到您正在编写的语言的影响,也不会影响您所拥有的系统调用的包装程序.

除此之外,Python和操作系统都可以进行读缓冲 - 实际上,当你从文件中读取一行时,Python /操作系统预计你可能也会对接下来的几行感兴趣,因此将它们读入main内存,以避免以后不得不一直推迟到磁盘本身.

  • 来自Python的@jramm,`open`采用可选的`buffering`参数.0表示关闭缓冲,1表示每次写入换行符时刷新缓冲区(行缓冲),其他正整数表示缓冲区大小(以字节为单位); 负值使用默认值.Python 2和Python 3之间的默认值发生了变化 - Python 2文档称它"通常"是完全缓冲的(缓冲区大小是文件大小)或行缓冲,具体取决于文件类型; 在Python 3中,它是针对ttys的行缓冲,否则是一种启发式.默认值通常已经调整,这就是默认值. (2认同)