关于Python多进程的初学者问题?

3 投票
3 回答
638 浏览
提问于 2025-04-16 07:29

我在数据库里有很多记录想要处理。简单来说,我想对文本字符串中的一些部分进行多次正则表达式替换,最后再把处理好的内容写回数据库。

我想知道使用多进程处理是否能加快完成这些任务的时间。我运行了一个命令:

multiprocessing.cpu_count

结果显示有8个处理器。我尝试了一些代码:

process = []
for i in range(4):
    if i == 3:
        limit = resultsSize - (3 * division)
    else:
        limit = division

    #limit and offset indicates the subset of records the function would fetch in the db
    p = Process(target=sub_table.processR,args=(limit,offset,i,))
    p.start()
    process.append(p)
    offset += division + 1

for po in process:
    po.join()

但看起来所花的时间比用单线程运行还要长。这是为什么呢?有没有人能告诉我这是合适的情况,还是我哪里做错了?

3 个回答

1

一般来说,多核或多处理器的处理方式在你的问题是“CPU受限”的时候最有效,也就是说,程序大部分时间都在让CPU尽可能快地运行。

根据你的描述,你的问题是“IO受限”的:从硬盘获取数据到CPU的过程非常慢,而CPU的工作速度很快(因为它的任务很简单)。

所以,提升CPU的运算速度对整体效果并没有太大帮助。

5

为什么会这样呢?

有没有人能告诉我,在什么情况下多进程能提高性能呢?

这里有个小窍门。

多进程只有在你的瓶颈是一个共享的资源时才有帮助。

共享资源(比如数据库)会被多个进程同时使用,这样反而没什么实际好处。

要找到一个不共享的资源,你需要有独立的对象。比如说,已经在内存中的一个列表。

如果你想从数据库中获取数据,你需要启动8个进程,然后这些进程就不再做数据库的工作了。所以,有时候一个中心查询把工作分配给不同的处理器是有好处的。

或者是8个不同的文件。需要注意的是,文件系统整体上是一个共享资源,有些文件访问方式涉及到共享像硬盘或目录这样的东西。

或者是8个小步骤的流水线。标准的Unix流水线技巧 query | process1 | process2 | process3 >file 比其他方法更有效,因为流水线中的每个阶段都是完全独立的。

还有另一个窍门。

你的计算机系统(操作系统、设备、数据库、网络等)非常复杂,简单的理论根本无法解释性能问题。你需要(a)进行多次测量和(b)尝试几种不同的算法,直到你理解所有的自由度。

像“在什么情况下多进程能提高性能?”这样的问题没有简单的答案。

如果想要一个简单的答案,你需要一个简单得多的操作系统。比如说,设备少一点,没有数据库和网络等。由于你的操作系统很复杂,所以这个问题没有简单的答案。

1

这里有几个问题:

  1. 在你的 processR 函数里,是一次性从数据库里获取很多记录,还是每次只取一行?(每次取一行会非常耗费性能。)

  2. 这可能不适合你的具体应用,但因为你是要处理“所有内容”,使用数据库可能会比用普通文件慢。数据库是为了处理逻辑查询而优化的,而不是顺序处理。在你的情况下,能不能把整个表的列导出到一个CSV文件中,处理完后再把结果导入回来呢?

希望这能帮到你。

撰写回答