使用多处理时拥有全局变量是否有效?
is it efficient to have a global variable when using multiprocessing?
请考虑这个很酷的设置:
from multiprocessing import Pool, cpu_count
import pandas as pd
import numpy as np
def helper(master_df):
max_index = master_df['key'].max()
min_index = master_df['key'].min()
#note how slave is defined before running the multiprocessing
return slave.iloc[min_index:max_index,]
from datetime import datetime
master = pd.DataFrame({'key': [1,2,3,4,5,6,7,8,9,10]})
slave = pd.DataFrame({'key': [1,2,3,4,5,6,7,8,9,10],
'value' : ['a','b','c','d','e','f','g','h','i','j']})
if __name__ == '__main__':
startTime = datetime.now()
p = Pool(cpu_count() - 1)
ret_list = p.map(helper, [master.iloc[1:5,], master.iloc[5:10,]])
print datetime.now() - startTime
print ret_list
本质上,我在内存中有两个数据帧。
正如您在主多处理代码中所见,p.map
接收 master
数据帧的两个块作为参数。
然后,(我想)multiprocessing
产生的每个进程将访问 slave
数据帧并使用它(无需修改)。实际上,您可以在 helper
函数中看到每个进程将 slice
slave
数据帧并用它进行一些计算。
我的问题是:在每个进程访问的全局命名空间中定义一个数据帧是否有效?我不确定在 RAM 利用率方面会发生什么(slave
是否在每个进程的内存中重复?)。这不是一个好主意,因为实际上 master
和 slave
都很大。
我想另一种方法是将 tuple
发送到 p.map
,其中包含分块的 master
和相应的切片 slave
数据帧。不确定这是个好主意(以及如何正确执行)?
有什么想法吗?
谢谢!
这令人惊讶地取决于操作系统,因为 multiprocessing
is implemented differently in Windows and Linux。
在 Linux 中,进程是通过 fork
变体创建的,其中子进程最初与父进程共享相同的地址,然后执行 COW (写时复制)。在 Linux 下,我经常让子进程访问一个只读的全局 DataFrame,一切都很好(包括性能)。
在 Windows 中,在幕后,很明显,整个过程都在旋转,你可能会因为将 DataFrame 复制到它而导致性能下降(除非它完成的处理是大到可以忽略成本),但我从未在 Windows 上使用过 Python,所以没有使用它的经验。
编辑
使用 joblib
和 DataFrames 的示例:
import joblib
import pandas as pd
df = pd.DataFrame(dict(a=[1, 3], b=[2, 3]))
def foo(i, df):
return df + i
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(foo)(i, df) for i in range(10))
您也可以使用 df
作为全局变量:
def foo(i):
return df + i
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(foo)(i) for i in range(10))
请考虑这个很酷的设置:
from multiprocessing import Pool, cpu_count
import pandas as pd
import numpy as np
def helper(master_df):
max_index = master_df['key'].max()
min_index = master_df['key'].min()
#note how slave is defined before running the multiprocessing
return slave.iloc[min_index:max_index,]
from datetime import datetime
master = pd.DataFrame({'key': [1,2,3,4,5,6,7,8,9,10]})
slave = pd.DataFrame({'key': [1,2,3,4,5,6,7,8,9,10],
'value' : ['a','b','c','d','e','f','g','h','i','j']})
if __name__ == '__main__':
startTime = datetime.now()
p = Pool(cpu_count() - 1)
ret_list = p.map(helper, [master.iloc[1:5,], master.iloc[5:10,]])
print datetime.now() - startTime
print ret_list
本质上,我在内存中有两个数据帧。
正如您在主多处理代码中所见,p.map
接收 master
数据帧的两个块作为参数。
然后,(我想)multiprocessing
产生的每个进程将访问 slave
数据帧并使用它(无需修改)。实际上,您可以在 helper
函数中看到每个进程将 slice
slave
数据帧并用它进行一些计算。
我的问题是:在每个进程访问的全局命名空间中定义一个数据帧是否有效?我不确定在 RAM 利用率方面会发生什么(slave
是否在每个进程的内存中重复?)。这不是一个好主意,因为实际上 master
和 slave
都很大。
我想另一种方法是将 tuple
发送到 p.map
,其中包含分块的 master
和相应的切片 slave
数据帧。不确定这是个好主意(以及如何正确执行)?
有什么想法吗? 谢谢!
这令人惊讶地取决于操作系统,因为 multiprocessing
is implemented differently in Windows and Linux。
在 Linux 中,进程是通过
fork
变体创建的,其中子进程最初与父进程共享相同的地址,然后执行 COW (写时复制)。在 Linux 下,我经常让子进程访问一个只读的全局 DataFrame,一切都很好(包括性能)。在 Windows 中,在幕后,很明显,整个过程都在旋转,你可能会因为将 DataFrame 复制到它而导致性能下降(除非它完成的处理是大到可以忽略成本),但我从未在 Windows 上使用过 Python,所以没有使用它的经验。
编辑
使用 joblib
和 DataFrames 的示例:
import joblib
import pandas as pd
df = pd.DataFrame(dict(a=[1, 3], b=[2, 3]))
def foo(i, df):
return df + i
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(foo)(i, df) for i in range(10))
您也可以使用 df
作为全局变量:
def foo(i):
return df + i
from joblib import Parallel, delayed
Parallel(n_jobs=2)(delayed(foo)(i) for i in range(10))