【问题标题】:How to manage scope using multiprocessing如何使用多处理管理范围
【发布时间】:2019-07-08 22:40:10
【问题描述】:

我正在尝试实现一个使用 python multiprocessing 的函数以加快计算速度。我正在尝试创建一个成对距离矩阵,但使用 for 循环的实现需要 8 个多小时。

此代码似乎运行得更快,但是当我打印矩阵时,矩阵中全是零。当我打印函数中的行时,它似乎可以工作。我认为是范围问题,但我不明白如何处理。

import multiprocessing
import time
import numpy as np

def MultiProcessedFunc(i,x):
    for j in range(i,len(x)):
        time.sleep(0.08)
        M[i,j] = (x[i]+x[j])/2
    print(M[i,:]) # Check if the operation works
    print('')

processes = []

v = [x+1 for x in range(8000)]
M = np.zeros((len(v),len(v)))

for i in range(len(v)):
    p = multiprocessing.Process(target = MultiProcessedFunc, args =(i,v))
    processes.append(p)
    p.start()

for process in processes:
    process.join()
end = time.time()

print('Multiprocessing: {}'.format(end-start))
print(M)

【问题讨论】:

标签: python python-multiprocessing multiprocess


【解决方案1】:

不幸的是,您的代码无法以这种方式编写。多进程产生独立的进程,这意味着内存空间是独立的!一个子流程所做的更改不会反映在其他流程或您的父流程中。

严格来说,这不是范围界定问题。范围是在单个解释器进程中定义的。

模块does provide means of sharing memory between processes,但这是有代价的(由于锁定问题等原因,共享内存要慢得多。

现在,numpy 有一个不错的功能:it releases the GIL during computation。这意味着使用多个threading 而不是multiprocessing 应该会给您带来一些好处,只需对代码进行少量其他更改,只需将import multiprocessing 替换为import threadingmultiprocessing.Processthreading.Thread。代码应该产生正确的结果。在我的机器上,删除打印语句和它在 8 秒内运行的 sleep 代码:

Multiprocessing: 7.48570203781
[[1.000e+00 1.000e+00 2.000e+00 ... 3.999e+03 4.000e+03 4.000e+03]
 [0.000e+00 2.000e+00 2.000e+00 ... 4.000e+03 4.000e+03 4.001e+03]
 [0.000e+00 0.000e+00 3.000e+00 ... 4.000e+03 4.001e+03 4.001e+03]
 ...
 [0.000e+00 0.000e+00 0.000e+00 ... 7.998e+03 7.998e+03 7.999e+03]
 [0.000e+00 0.000e+00 0.000e+00 ... 0.000e+00 7.999e+03 7.999e+03]
 [0.000e+00 0.000e+00 0.000e+00 ... 0.000e+00 0.000e+00 8.000e+03]]

另一种方法是让您的子流程返回结果,然后将结果合并到您的主流程中。

【讨论】:

  • 绝对可以使用来自multiprocessing 的共享内存数组,但这是重写为numpy 数组的经典案例(如您所指)。
  • @MikeMcKerns 是的,多处理数组不提供向量操作,这意味着它会方式变慢。
  • 问题是在原始程序中我没有一个带有数字的列表,而是一个带有字符串的列表,我不能使用 numpy
  • 另外,睡眠部分是为了模拟真实代码中发生的事情
  • @GiuseppeMinardi 使用数字和字符串几乎总是需要不同的方法。如果没有详细信息,我们无法为您提供比我写的更好的建议:如果您需要共享内存,则必须使用 multiprocessing api,替代方法是使用 multiprocessing.Pool 方法返回结果并在之后组合它们。哪一种效果更好取决于您将要做什么,您可能需要对这两种解决方案进行概要分析,以查看哪一种更适合您的情况。
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
  • 2014-11-11
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多