使用多处理时 Pickle 中的 MemoryError
MemoryError in Pickle while using Multiprocessing
我正在 运行宁 monte carlo 一些物理系统的模拟,我需要增加模拟时间步长的粒度(所以 n_timesteps=t/dt 其中 t 是固定的)。这显然会导致每次模拟的 运行 时间更长(以及内存使用量增加)。
因此,我更改了我的代码以使用使用 pythons 多处理的所有处理器。
这适用于粗略的模拟(较大的 dt),但一旦我减少 dt,我 运行 就会出现酸洗错误:
multiprocessing.pool.MaybeEncodingError: Error sending result: '<multiprocessing.pool.ExceptionWithTraceback object at 0x000000000B5D6EC8>'. Reason: 'PicklingError("Can't pickle <class 'MemoryError'>: it's not the same object as builtins.MemoryError")'
我使用了一个基本上可以完成所有模拟的包。所以我的代码看起来类似于:
import numpy as np
import multiprocessing as mp
from specific_package import system_simulator
def subsimulation(parameter, other_parameters):
n_montecarlo = 2
simulator = system_simulator(other_parameters, n_montecarlo)
# parameter is an numpy array of shape(n_timesteps, 13)
simulator.set_parameters(parameter) # At this point the error gets thrown
results = simulator.calculate()
# results will be a list of length n_montecarlo with each element contatining a list of length
# n_timesteps each containg a (4, 4) matrix (in a for the package specific dataformat)
# results is then reduced to 4 numpy arrays of length n_timesteps each:
a, b, c, d = np.ones(n_timesteps), np.ones(n_timesteps), np.ones(n_timesteps), np.ones(n_timesteps)
return [a, b, c, d]
def run_simulation(foo):
# does some stuff then run the simulations in parallel:
runs = [i+1 for i in range(96)] # As in total I want to have ~200 single simulations
pool = mp.Pool(mp.cpu_count())
results = pool.starmap_async(subsimulation, [(parameter, other_parameters) for run in runs]).get()
pool.close()
avg_res = np.mean(np.array(results), axis=0)
return [avg_res[0], avg_res[1], avg_res[2], avg_res[3]]
例如,这不适用于 n_timesteps = 60000
,我认为这实际上应该是可管理的。
我已经将每个子模拟中的模拟数量减少到 2,这样内存使用量就很小(以换取速度)并且 pickle 不必处理大型数组。
但我真正不明白的是,在执行 set_parameters 时会抛出错误,我不希望发生任何 pickle 操作。
每个模拟都是相互独立的,并且需要相当长的时间,所以我想:多处理在这里是个好主意。然而,由于我不是很有经验,尤其是在多处理方面,我真的不确定什么是解决这个问题的合适方法。
(我 运行 Windows 具有 8 个内核和 8GB 内存 - 如果需要更多信息,我很乐意提供)
好的,事实证明,问题实际上不是由 pickle 本身引起的,而是由模拟器包更新中的错误引起的,该错误试图创建一个大小为 (n_timesteps, n_timesteps)。抱歉造成混淆。
我正在 运行宁 monte carlo 一些物理系统的模拟,我需要增加模拟时间步长的粒度(所以 n_timesteps=t/dt 其中 t 是固定的)。这显然会导致每次模拟的 运行 时间更长(以及内存使用量增加)。 因此,我更改了我的代码以使用使用 pythons 多处理的所有处理器。 这适用于粗略的模拟(较大的 dt),但一旦我减少 dt,我 运行 就会出现酸洗错误:
multiprocessing.pool.MaybeEncodingError: Error sending result: '<multiprocessing.pool.ExceptionWithTraceback object at 0x000000000B5D6EC8>'. Reason: 'PicklingError("Can't pickle <class 'MemoryError'>: it's not the same object as builtins.MemoryError")'
我使用了一个基本上可以完成所有模拟的包。所以我的代码看起来类似于:
import numpy as np
import multiprocessing as mp
from specific_package import system_simulator
def subsimulation(parameter, other_parameters):
n_montecarlo = 2
simulator = system_simulator(other_parameters, n_montecarlo)
# parameter is an numpy array of shape(n_timesteps, 13)
simulator.set_parameters(parameter) # At this point the error gets thrown
results = simulator.calculate()
# results will be a list of length n_montecarlo with each element contatining a list of length
# n_timesteps each containg a (4, 4) matrix (in a for the package specific dataformat)
# results is then reduced to 4 numpy arrays of length n_timesteps each:
a, b, c, d = np.ones(n_timesteps), np.ones(n_timesteps), np.ones(n_timesteps), np.ones(n_timesteps)
return [a, b, c, d]
def run_simulation(foo):
# does some stuff then run the simulations in parallel:
runs = [i+1 for i in range(96)] # As in total I want to have ~200 single simulations
pool = mp.Pool(mp.cpu_count())
results = pool.starmap_async(subsimulation, [(parameter, other_parameters) for run in runs]).get()
pool.close()
avg_res = np.mean(np.array(results), axis=0)
return [avg_res[0], avg_res[1], avg_res[2], avg_res[3]]
例如,这不适用于 n_timesteps = 60000
,我认为这实际上应该是可管理的。
我已经将每个子模拟中的模拟数量减少到 2,这样内存使用量就很小(以换取速度)并且 pickle 不必处理大型数组。
但我真正不明白的是,在执行 set_parameters 时会抛出错误,我不希望发生任何 pickle 操作。
每个模拟都是相互独立的,并且需要相当长的时间,所以我想:多处理在这里是个好主意。然而,由于我不是很有经验,尤其是在多处理方面,我真的不确定什么是解决这个问题的合适方法。 (我 运行 Windows 具有 8 个内核和 8GB 内存 - 如果需要更多信息,我很乐意提供)
好的,事实证明,问题实际上不是由 pickle 本身引起的,而是由模拟器包更新中的错误引起的,该错误试图创建一个大小为 (n_timesteps, n_timesteps)。抱歉造成混淆。