python 多处理 - OverflowError('cannot serialize a bytes object larger than 4GiB')
python multiprocessing - OverflowError('cannot serialize a bytes object larger than 4GiB')
我们是 运行 使用 multiprocessing
库 (python 3.6
) 的脚本,其中一个大 pd.DataFrame
作为参数传递给函数:
from multiprocessing import Pool
import time
def my_function(big_df):
# do something time consuming
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(my_function,(big_df ,))
output = {u : res[id].get() for id in id_list}
问题是我们从 pickle
库中收到错误。
Reason: 'OverflowError('cannot serialize a bytes objects larger than
4GiB',)'
我们知道 pickle v4
可以序列化更大的对象 question related, link,但我们不知道如何修改 multiprocessing
正在使用的协议。
有人知道该怎么办吗?
谢谢!!
显然有空位 issue about this topic , and there is a few related initiatives described on this particular answer. I Found a way to change the default pickle
protocol that is used in the multiprocessing
library based on this 。正如评论中指出的那样,此解决方案 仅适用于 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
这可能会解决溢出的问题。
但是,警告,您可能会考虑在做任何事情之前阅读 ,否则您可能会遇到与我相同的错误:
'i' format requires -2147483648 <= number <= 2147483647
(这个错误的原因在上面的中有很好的解释)。长话短说,multiprocessing
使用 pickle
协议通过其所有进程发送数据,如果您已经达到 4gb
限制,那可能意味着您可以考虑将函数重新定义为 "void" 方法而不是 input/output 方法。所有这些 inbound/outbound 数据都会增加 RAM 使用率,可能由于构造(我的情况)而效率低下,最好将所有进程指向同一个对象,而不是为每次调用创建一个新副本。
希望这对您有所帮助。
Pablo 的补充回答
下面的问题可以解决Python3.8,如果你用这个版本没问题python:
'i' format requires -2147483648 <= number <= 2147483647
我们是 运行 使用 multiprocessing
库 (python 3.6
) 的脚本,其中一个大 pd.DataFrame
作为参数传递给函数:
from multiprocessing import Pool
import time
def my_function(big_df):
# do something time consuming
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(my_function,(big_df ,))
output = {u : res[id].get() for id in id_list}
问题是我们从 pickle
库中收到错误。
Reason: 'OverflowError('cannot serialize a bytes objects larger than 4GiB',)'
我们知道 pickle v4
可以序列化更大的对象 question related, link,但我们不知道如何修改 multiprocessing
正在使用的协议。
有人知道该怎么办吗? 谢谢!!
显然有空位 issue about this topic , and there is a few related initiatives described on this particular answer. I Found a way to change the default pickle
protocol that is used in the multiprocessing
library based on this
解决方案:
你先创建一个新的分离模块
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
这可能会解决溢出的问题。
但是,警告,您可能会考虑在做任何事情之前阅读
'i' format requires -2147483648 <= number <= 2147483647
(这个错误的原因在上面的multiprocessing
使用 pickle
协议通过其所有进程发送数据,如果您已经达到 4gb
限制,那可能意味着您可以考虑将函数重新定义为 "void" 方法而不是 input/output 方法。所有这些 inbound/outbound 数据都会增加 RAM 使用率,可能由于构造(我的情况)而效率低下,最好将所有进程指向同一个对象,而不是为每次调用创建一个新副本。
希望这对您有所帮助。
Pablo 的补充回答
下面的问题可以解决Python3.8,如果你用这个版本没问题python:
'i' format requires -2147483648 <= number <= 2147483647