python - 如何使用多处理管理范围
问题描述
我正在尝试实现一个使用 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)
解决方案
不幸的是,您的代码无法以这种方式编写。多进程产生独立的进程,这意味着内存空间是独立的!一个子流程所做的更改不会反映在其他流程或您的父流程中。
严格来说,这不是范围界定问题。范围是在单个解释器进程中定义的。
该模块确实提供了在进程之间共享内存的方法,但这是有代价的(由于锁定问题等原因,共享内存要慢得多。
现在,numpy 有一个很好的特性:它在计算期间释放 GIL。这意味着使用 multithreading
而不是multiprocessing
应该会给您带来一些好处,只需对代码进行少量其他更改,只需替换import multiprocessing
为import threading
和multiprocessing.Process
into threading.Thread
。代码应该产生正确的结果。在我的机器上,删除打印语句及其sleep
在 8 秒内运行的代码:
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]]
另一种方法是让您的子流程返回结果,然后将结果合并到您的主流程中。
推荐阅读
- angular - 如何在Angular的Ignite UI中导出所选记录的excel
- spring - Spring:正确使用 lombock Builder
- openlayers - Openlayers:是否可以在多面体周围添加半径?
- android - 有没有办法向片段视图发出数据已传递给参数的信号?
- node.js - 为什么我的 Node API 可以在本地工作,但不能在 Heroku 上工作?
- java - 在 LispWorks 的 Java 接口中使用枚举
- ubuntu - 根据第一列 ID 连接两个文件
- html - 为什么我会收到此验证错误?“表格正文中的开始标签”
- javascript - 如何收听 aws cognito 中更改的身份验证状态?
- javascript - 首先尝试使用 vue.js。使用路由器的问题