Python中的多进程处理列表参数

3

我正在编写我的第一个Python多进程程序。

我想创建一个值列表以进行处理,8个进程(CPU核心数)将消耗和处理该值列表。

我编写了以下Python代码:

__author__ = 'Rui Martins'

from multiprocessing import cpu_count, Process, Lock, Value

def proc(lock, number_of_active_processes, valor):
    lock.acquire()
    number_of_active_processes.value+=1
    print "Active processes:", number_of_active_processes.value
    lock.release()
    # DO SOMETHING ...
    for i in range(1, 100):
        valor=valor**2
    # (...)
    lock.acquire()
    number_of_active_processes.value-=1
    lock.release()

if __name__ == '__main__':
    proc_number=cpu_count()
    number_of_active_processes=Value('i', 0)
    lock = Lock()
    values=[11, 24, 13, 40, 15, 26, 27, 8, 19, 10, 11, 12, 13]
    values_processed=0

    processes=[]
    for i in range(proc_number):
        processes+=[Process()]
    while values_processed<len(values):
        while number_of_active_processes.value < proc_number and values_processed<len(values):
            for i in range(proc_number):
                if not processes[i].is_alive() and values_processed<len(values):
                    processes[i] = Process(target=proc, args=(lock, number_of_active_processes, values[values_processed]))
                    values_processed+=1
                    processes[i].start()

            while number_of_active_processes.value == proc_number:
                # BUG: always number_of_active_processes.value == 8 :(
                print "Active processes:", number_of_active_processes.value

    print ""
    print "Active processes at END:", number_of_active_processes.value

我有以下问题:

  • 程序永远不会停止
  • 内存不足 enter image description here

Daniel Sanchez,我认为多进程与线程不同,并且使用多进程时GIL不会被锁定。 参见:https://dev59.com/TXA75IYBdhLWcg3w6Ndj?rq=1 - Rui Martins
是的,我在发布那个愚蠢的帖子后就想到了这一点,很抱歉 :/ - Netwave
2个回答

1
简化您的代码如下:
def proc(lock, number_of_active_processes, valor):
    lock.acquire()
    number_of_active_processes.value += 1
    print("Active processes:", number_of_active_processes.value)
    lock.release()
    # DO SOMETHING ...
    for i in range(1, 100):
        print(valor)
        valor = valor **2
    # (...)
    lock.acquire()
    number_of_active_processes.value -= 1
    lock.release()


if __name__ == '__main__':
    proc_number = cpu_count()
    number_of_active_processes = Value('i', 0)

    lock = Lock()
    values = [11, 24, 13, 40, 15, 26, 27, 8, 19, 10, 11, 12, 13]
    values_processed = 0

    processes = [Process() for _ in range(proc_number)]
    while values_processed < len(values)-1:
        for p in processes:
            if not p.is_alive():
                p = Process(target=proc,
                            args=(lock, number_of_active_processes, values[values_processed]))
                values_processed += 1
                p.start()

如果按照以上方式运行,添加print(valor)后,您将看到正在发生的事情,即指数增长valor直到内存耗尽,您不会卡在while循环中,而是卡在for循环中。这是在第12个进程中添加print(len(srt(valor)))后的输出,在几分之一秒后它仍在继续。
2
3
6
11
21
.........
59185
70726
68249
73004
77077
83805
93806
92732
90454
104993
118370
136498
131073

将以下内容翻译成中文:

只需将您的循环更改为以下内容:

for i in range(1, 100):
    print(valor)
    valor = valor *2

最后创建的数字是:

 6021340351084089657109340225536

使用您自己的代码,似乎会在 while 循环中卡住,但是其值在 for 循环中增长到与以下数字一样多的位数:
167609
180908
185464
187612
209986
236740
209986

而且......


嗨,谢谢,但我认为您无法更改代码,因为您的代码使用了8个以上进程。当您执行"p = Process(......"时,会创建和启动一个新进程,但不会替换原始进程列表中的“p”,而且“if not p.is_alive()”一直将返回“True”。例如: 列表=范围(15) 打印列表 对于l在列表中: 打印l l=0 print列表 - Rui Martins
抱歉,我的英语不太好,但是在我的代码中,我只运行8个进程(同时),而在你的代码中,你运行了13个(因为“values”的大小)。问题在于你的代码是正确的并且可以工作,但是我需要每个进程尽可能快地运行,所以我只运行8个进程,每个进程处理一个值,每当一个进程完成时,我就运行一个新的进程,直到所有值都被处理。感谢您的帮助 :) 真的,你的回答是最好的。 - Rui Martins
1
@RuiMartins,processes = [Process() for _ in range(proc_number)],只需循环处理进程列表就与您代码中的索引逻辑完全相同,当您想要使用索引时,可以使用enumerate进行索引processes[i] = Process。http://pastebin.com/ksQbvMET - Padraic Cunningham
1
好的,现在可以使用enumerate函数了;) 谢谢你花时间:) - Rui Martins

0
问题不在于你的多进程代码,而是在for循环中的pow运算符:
for i in range(1, 100):
        valor=valor**2

最终结果将是pow(val,2 ** 100),这太大了,计算它将耗费太多时间和内存。因此,您最后会遇到内存错误。

4 GB = 4 * pow(2, 10) * pow(2, 10) * pow(2, 20) * 8 bit = 2**35 bit

而对于您的最小数8:

pow(8, 2**100) = pow(2**3, 2**100) = pow(2, 3*pow(2, 100))
pow(2, 3*pow(2, 100))bit/4GB = 3*pow(2, 100-35) = 3*pow(2, 65)

它需要3*pow(2, 65)次4 GB内存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接