【问题标题】:Multiprocessing in Python to process a list of parametersPython中的多处理来处理参数列表
【发布时间】:2015-12-31 15:41:10
【问题描述】:

我正在用 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

而且,我有以下问题:

  • 程序永不停止
  • 内存不足

【问题讨论】:

  • Daniel Sanchez,我认为多处理与线程不同,GIL 并没有被多处理锁定。见:stackoverflow.com/questions/3044580/…
  • 是的,我只是在发布了我的愚蠢之后才想到它,对不起:/

标签: python python-2.7 multiprocessing


【解决方案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) 添加的那样运行它,你会看到正在发生的事情,你的勇气会呈指数级增长到内存不足的地步,你不会被困在你被困在 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 循环中的 valor 正在增长到具有与以下数字一样多的数字:

167609
180908
185464
187612
209986
236740
209986

然后……

【讨论】:

  • 您好,谢谢,但我认为您不能更改代码,因为您的代码使用了 8 个以上的进程,因为当您执行“p = Process(...”时,您将创建并启动一个新的进程,但不会替换原始列表 os 进程中的“p”,并且“如果不是 p.is_alive()”将始终返回“True”。示例:lista = range(15) print lista for l在列表中:打印 l l=0 打印列表
  • 抱歉,我的英语说得不太好,但是,在我的代码中我只运行 8 个进程(同时),而在你的代码中你运行 13 个(因为“值”的大小。问题是您的代码正确且有效,但我需要每个进程尽可能快,然后我只运行 8 个进程,每个进程都有一个值,每次一个进程完成时,我运行一个新进程直到每个值都被处理。感谢您的帮助:) 真的你有最好的答案
  • @RuiMartins, processes = [Process() for _ in range(proc_number)] 并且只是循环遍历进程列表与代码中的索引逻辑完全相同,您可以在需要时使用枚举来索引processes[i] = Process pastebin.com/ksQbvMET
  • 好的,现在可以使用枚举了 ;) 谢谢你的时间 :)
【解决方案2】:

问题不在于您的多处理代码。就是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 内存。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 2020-05-15
    • 1970-01-01
    • 1970-01-01
    • 2015-07-15
    • 2018-08-18
    • 2022-12-09
    相关资源
    最近更新 更多