同时写入大量文件的最佳进程数

时间:2013-02-18 18:51:50

标签: python multiprocessing

我想同时写很多文件(比如10000个文件)。我发现我可以使用多处理。我随意选择使用100个进程来编写这些文件。我需要知道是否有办法找到最佳的进程数量?此代码或所有进程自动终止后,我还需要进行任何清理吗?

我还想知道是否有更有效的方法同时编写大量文件。

from multiprocessing import Pool

def write(x):
    fopen=open('file_'+str(x),'w')
    fopen.write('anything')
    fopen.close()

if __name__ == '__main__':
    pool = Pool(processes=100)              
    pool.map(write, range(10000))          

1 个答案:

答案 0 :(得分:1)

首先,对于纯I / O,threading可能与multiprocessing一样好,而且往往更好。它也没有关于"我需要任何清理的谜团#34;。所以,你可能想测试一下。

其次,如果你想知道最快的方法,那么唯一真正的选择是使用timeit,或者你的shell time或等同物进行测试。它听起来你已经做到了。如果您正在寻找一种基于信息以编程方式确定理想池大小的方法,您可以阅读有关系统的信息(SSD与10K HD对比5200 HD与远程共享​​,LAN与WAN,快速LAN vs.慢LAN,SMB与NFS,Windows与POSIX等),您可能需要在各种机器上进行测试并进行一些统计分析。其中一些信息不是静态可用的,因此您确实需要启动该过程,然后随时调整池大小。它会变得非常复杂 - 我猜这一切工作只能让你在大部分时间内获得10%的收益。

如果你真的需要从文件I / O中挤出最后几个百分点,你可能需要降低一两级。

至少,您可能希望将Python和/或stdio缓冲区从等式中删除(假设文件确实很小)并使用os.openos.write。创建字节的原始缓冲区而不是字符串甚至可能会有所帮助(特别是如果这是Python 3)。如果您实际上对每个文件,甚至只是对许多文件写入完全相同的内容,使用相同的缓冲区可能允许操作系统识别您将相同的内容写入多个文件,这意味着缓存可以是完美的,而不仅仅是接近完美。

您甚至可能希望下载到特定于平台的API。例如,在Windows上,使用重叠I / O允许操作系统尽可能有效地调度写入,并且在IOCP周围创建本机线程池来处理完成也会消除写入调度之上的所有开销。 (您可以通过CreateFileWriteFileEx访问ctypeswin32api等。或者谷歌搜索" IOCP Python"以获取示例代码 - 这些都是是不完整的或部分无关的,特别是因为它的大多数是为c10k套接字服务器而设计的,但它至少会证明足以将其余部分放在一起,在MSDN和试错的帮助下。)我不能想想POSIX上的任何等价物(好吧,aio_write相当于WriteFileEx,但据我所知,它不会在任何真实世界的* nix平台上提供帮助。

或者,您可能希望将向上移动一步。如果您真的将相同的数据写入所有文件或只是许多文件,为什么不将它写入一个文件然后要求操作系统复制该文件?它可能能够做得更好。

或者,甚至更简单 - 并且速度更快 - 将其写入一个文件,然后将其余部分创建为硬链接或符号链接。


因为您询问了最后一个选项:

创建链接背后的想法是您只创建一个文件,但创建10000个不同的名称来访问它。

这意味着如果您编辑一个文件,则会编辑所有10000个文件。如果这不是你想要的,那么链接就不合适了。

但如果它是你想要的,有两种基本类型的链接:硬链接和符号链接。

现代文件系统允许多个目录条目指向同一文件。创建hard link是一种创建另一个目录条目的方法,该条目指向与现有文件相同的文件。在Python中,您使用os.link执行此操作。所以:

with open('file_0', 'w') as f:
    f.write('anything')
for i in range(1, 10000):
    os.link('file_0', 'file_{}'.format(i))

现在,您的文件系统有10000个名为file_0file_9999的条目,但它们是磁盘上相同实际数据的所有名称。编辑一个,另一个9999全部改变。删除一个,另一个9999仍在那里。

硬链接存在一些小问题,一个主要问题。小问题是每个平台都有关于除常规文件之外的硬链接的不同规则,并且通常不能跨文件系统进行硬链接。主要问题是Windows。首先,你需要像(在我的头脑中)Vista和NTFS 6获得全面支持,Win2000和NTFS 4以获得部分支持。但更重要的是,os.link在Windows上不存在。因此,您必须使用ctypeswin32api来调用基础CreateHardLink函数(或subprocess来运行mklinkfsutil命令

symbolic link是更高层次的想法。它是一种通过路径引用另一个文件的特殊文件。这意味着您可以阅读有关符号链接本身的信息(请参阅statlstat),创建保留链接信息的tarball等。这也意味着如果删除file_0,则全部其他人成为断开的链接,指向一个不存在的文件。无论如何,在Python中,您使用os.symlink来创建它们(使用与上面完全相同的代码)。

符号链接没有硬链接的大多数限制,但是对于Windows来说它们更糟糕 - 在Vista之前根本没有符号链接,普通文件与目录的规则不同,链接数量限制可以是遍历,需要非管理员用户不具备的特权等。当然,您无法使用Python中的os.symlink

还有一些特定于平台的内容,例如Windows快捷方式和Mac别名,它们与符号链接具有相似但不相同的功能。