我们正在使用python 3.6
库(pd.DataFrames
)运行脚本,其中大from multiprocessing import Pool
import time
def f(x):
# do something time conssuming
time.sleep(50)
if __name__ == '__main__':
with Pool(10) as p:
res = {}
output = {}
for id, big_df in some_dict_of_big_dfs:
res[id] = p.apply_async(f,(big_df ,))
output = {u : res[id].get() for id in id_list}
通过流程传递:
pickle
问题是我们从pickle v4
库中获取了一个错误。
原因:“ OverflowError('无法序列化大于 4GiB',)'
我们知道multiprocessing
可以序列化较大的对象question related,link,但是我们不知道如何修改target="_blank"
使用的协议。
有人知道该怎么做吗? 谢谢!!
答案 0 :(得分:3)
显然,有关此主题(Issue)尚有一个未解决的问题,并且在此特定答案(link)上描述了一些相关的举措。我找到了一种基于此答案(link)来更改pickle
库中使用的默认multiprocessing
协议的方法。正如评论中指出的那样,该解决方案仅适用于Linux和OS多处理库
您首先创建一个新的分隔模块
pickle4reducer.py
from multiprocessing.reduction import ForkingPickler, AbstractReducer
class ForkingPickler4(ForkingPickler):
def __init__(self, *args):
if len(args) > 1:
args[1] = 2
else:
args.append(2)
super().__init__(*args)
@classmethod
def dumps(cls, obj, protocol=4):
return ForkingPickler.dumps(obj, protocol)
def dump(obj, file, protocol=4):
ForkingPickler4(file, protocol).dump(obj)
class Pickle4Reducer(AbstractReducer):
ForkingPickler = ForkingPickler4
register = ForkingPickler4.register
dump = dump
然后,在您的主脚本中,需要添加以下内容:
import pickle4reducer
import multiprocessing as mp
ctx = mp.get_context()
ctx.reducer = pickle4reducer.Pickle4Reducer()
with mp.Pool(4) as p:
# do something
那可能会解决溢出的问题... 但是,警告,您可能会在做任何事情之前考虑阅读this ,否则可能会遇到与我相同的错误:
'i'格式需要-2147483648 <=数字<= 2147483647
(此错误的原因在上面的链接中有很好的解释)。简而言之,multiprocessing
使用pickle
协议通过其所有过程发送数据,如果您已经达到了4gb
的限制,则可能意味着您可能会考虑将函数重新定义为“ void ”方法而不是输入/输出方法。所有这些入站/出站数据都会增加RAM使用率,在构造上可能效率低下(我的情况),并且将所有进程都指向同一个对象而不是为每个调用创建一个新副本可能更好。
希望这会有所帮助。
答案 1 :(得分:0)
补充 Pablo 的回答
Python3.8可以解决以下问题,如果你用这个版本的python没问题:
'i' format requires -2147483648 <= number <= 2147483647