我正在运行一些物理系统的蒙特卡罗模拟,我需要增加模拟时间步长的粒度(因此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_参数时会抛出错误,我不希望出现任何pickle操作
每个模拟都是相互独立的,并且需要相当长的时间,所以我认为:多处理在这里是个好主意。然而,由于我不是很有经验,特别是在多重处理方面,我真的不确定什么是解决这个问题的合适方法。 (我使用8核和8GB ram运行Windows-如果需要更多信息,我很乐意提供)
好的,事实证明,问题实际上不是由pickle本身引起的,而是由模拟器包更新中的一个bug引起的,它试图创建一个大小为(n_timesteps,n_timesteps)的numpy数组。很抱歉搞混了
相关问题 更多 >
编程相关推荐