Python是否自动并行化I/O和CPU或内存绑定部分?

3 投票
5 回答
2490 浏览
提问于 2025-04-15 11:34

这是一个关于之前问题的后续提问,链接在这里:之前的问题

考虑一下这段代码,它比之前问题中的代码更复杂一些(但仍然比我真正的代码简单很多)。

import sys
data=[]

for line in open(sys.argv[1]):
    data.append(line[-1])

print data[-1]

我原本以为运行时间会更长一些(我的基准文件有65150224行),可能会长很多。但实际上并不是这样,它在和之前一样的硬件上运行了大约2分钟!

那么,data.append()是不是很轻量呢?我不这么认为,所以我写了这段假代码来测试一下:

data=[]
counter=0
string="a\n"

for counter in xrange(65150224):
    data.append(string[-1])

print data[-1]

这段代码的运行时间在1.5到3分钟之间(运行时间差异很大)。

为什么我在前面的程序中没有得到3.5到5分钟的运行时间呢?显然,data.append()是在和输入输出同时进行的。

这可是个好消息!

但这到底是怎么回事呢?这是一个文档中提到的特性吗?我的代码有没有什么要求需要遵循,以便尽可能地让它发挥作用(除了平衡输入输出和内存/CPU的活动)?还是说这只是普通的缓冲/缓存在起作用?

我再次标记了“linux”这个问题,因为我只对与linux相关的答案感兴趣。如果你觉得有必要,也可以提供与操作系统无关的,或者其他操作系统的答案。

5 个回答

1

你文件里的每一行有多长呢?如果它们不是很长(大约在1K以下的行都算短),那么你可能会因为输入缓冲而看到性能提升。

1

你觉得 list.append() 为什么会是一个比较慢的操作呢?其实它非常快。因为列表内部使用了一种指针数组来存放里面的对象,这些指针是以越来越大的块来分配的。所以每次添加元素的时候,并不需要重新分配整个数组,大部分情况下只需要增加长度计数器,设置一个指针,然后增加引用计数就可以了。

8

很明显,data.append() 和输入输出(IO)是同时进行的。

我怕不是这样。虽然在Python中确实可以让输入输出和计算同时进行,但这并不是自动发生的。

你可以做的一件事是使用 posix_fadvise(2) 来告诉操作系统,你打算顺序读取文件(POSIX_FADV_SEQUENTIAL)。

在一些粗略的测试中,我对一个600兆的文件(一个ISO文件)执行“wc -l”命令时,性能提高了大约20%。每次测试都是在清空磁盘缓存后立即进行的。

如果你想在Python中使用fadvise,可以查看 python-fadvise

撰写回答