同时运行多个进程

16 投票
3 回答
51468 浏览
提问于 2025-04-18 00:14

我正在尝试用Python创建一个程序,想要同时在不同的处理器上运行15个相同的功能。为此,我查了一些资料,并使用了多进程中的Process工具,设置了下面的程序。

可惜的是,程序每次只顺序执行一个功能的实例(看起来是等一个完成后才会继续下一个循环的部分)。

from __future__ import print_function
from multiprocessing import Process
import sys
import os
import re

for i in range(1,16):
    exec("path%d = 0" % (i))
    exec("file%d = open('%d-path','a', 1)" % (i, i))

def stat(first, last):
    for j in range(1,40000):
        input_string = "water" + str(j) + ".xyz.geocard"
        if os.path.exists('./%s' % input_string) == True:
            exec("out%d = open('output%d', 'a', 1)" % (first, first))
            exec('print("Processing file %s...", file=out%d)' % (input_string, first))
            with open('./%s' % input_string,'r') as file:
                for line in file:
                    for i in range(first,last):
                        search_string = " " + str(i) + " path:"
                        for result in re.finditer(r'%s' % search_string, line):
                            exec("path%d += 1" % i)

            for i in range(first,last):
                exec("print(path%d, file=file%d)" % (i, i))  

processes = []

for m in range(1,16):
    n = m + 1
    p = Process(target=stat, args=(m, n))
    p.start()
    processes.append(p)

for p in processes:
    p.join()

我对编程还比较陌生,也没有并行处理的经验,所以任何帮助都非常感谢。

我把整个程序都放在上面了,把“某个功能”替换成了实际的功能,以证明这不是时间问题。这个程序处理所有40000个文件(每个文件都很大)可能需要几天的时间。

3 个回答

1

下面的代码可以同时运行10个进程,打印从 099 的数字。

*if __name__ == "__main__": 这行代码在Windows上运行进程时是必须的:

from multiprocessing import Process

def test():
    for i in range(0, 100):
        print(i)

if __name__ == "__main__": # Here
    process_list = []

    for _ in range(0, 10):
        process = Process(target=test)
        process_list.append(process)

    for process in process_list:
        process.start()

    for process in process_list:
        process.join()

而下面的代码是上面代码的简写形式,同样可以同时运行10个进程,打印从 099 的数字:

from multiprocessing import Process

def test():
    [print(i) for i in range(0, 100)]

if __name__ == "__main__":
    process_list = [Process(target=test) for _ in range(0, 10)]

    [process.start() for process in process_list]

    [process.join() for process in process_list]

下面是运行结果:

...
99
79
67
71
67
89
81
99
80
68
...
28

我觉得你遇到的问题是,在some_function这个函数里,你没有做足够的事情来观察到并行工作的效果。这个函数会启动一个进程,但在下一个进程启动之前,第一个进程就已经完成了。如果你在some_function里加入一个随机的等待时间,你会发现这些进程实际上是同时在运行的。

from multiprocessing import Process
import random
import time

def some_function(first, last):
    time.sleep(random.randint(1, 3))
    print first, last

processes = []

for m in range(1,16):
   n = m + 1
   p = Process(target=some_function, args=(m, n))
   p.start()
   processes.append(p)

for p in processes:
   p.join()

输出

2 3
3 4
5 6
12 13
13 14
14 15
15 16
1 2
4 5
6 7
9 10
8 9
7 8
11 12
10 11
3

你确定吗?我刚试了一下,结果对我来说是有效的;每次执行的结果都是乱序的,这说明它们是同时执行的。

看看你的函数。它需要“first”和“last”这两个参数,那么对于较小的值,它的执行时间是不是更短呢?如果是这样的话,你可以期待较小的参数会让运行时间更短,这样看起来就像是并行执行了。

ps ux | grep python | grep -v grep | wc -l
> 16

如果你重复执行代码(比如用一个bash脚本),你会发现每个进程都在启动。如果你想确认这一点,可以导入os模块,让函数打印出os.getpid(),这样你就能看到它们有不同的进程ID。

所以,确实要仔细检查你的结果,因为在我看来,你的代码似乎是正确地实现了并行执行!

撰写回答