我找不到更好的方法来描述我所面临的错误,但是每当我尝试将多处理实现为循环调用时,这个错误似乎都会出现。
我已经同时使用了sklearn.externals.joblib以及multiprocessing.Process但是错误虽然不同但是相似。
想要应用多处理的原始循环,其中一次迭代在单线程/进程中执行
for dd in final_col_dates:
idx1 = final_col_dates.tolist().index(dd)
dataObj = GetPrevDataByDate(d1, a, dd, self.start_hour_of_day)
data2 = dataObj.fit()
dataObj = GetAppointmentControlsSchedule(data2, idx1, d, final_col_dates_mod, dd, self.DC, frgt_typ_filter)
data3 = dataObj.fit()
if idx1 > 0:
data3['APPT_SCHD_ARVL_D_{}'.format(idx1)] = np.nan
iter += 1
days_out_vars.append(data3)
为了将上述代码snipet实现为Multi Processing,我创建了一个方法,除了 for循环之外,上面的代码除外。
使用Joblib,以下是我的代码片段。
Parallel(n_jobs=2)(
delayed(self.ParallelLoopTest)(dd, final_col_dates, d1, a, d, final_col_dates_mod, iter, return_list)
for dd in final_col_dates)
变量 return_list 是共享变量,它在方法ParallelLoopTest中执行。它被声明为:
manager = Manager()
return_list = manager.list()
使用上面的代码片段,我遇到以下错误:
Process SpawnPoolWorker-3:
Traceback (most recent call last):
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\process.py", line 249, in _bootstrap
self.run()
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\process.py", line 93, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\pool.py", line 108, in worker
task = get()
File "C:\Users\dkanhar\Anaconda3\lib\site-packages\sklearn\externals\joblib\pool.py", line 359, in get
return recv()
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\connection.py", line 251, in recv
return ForkingPickler.loads(buf.getbuffer())
TypeError: function takes at most 0 arguments (1 given)
我也尝试过多处理模块来执行上面提到的代码,但仍然遇到类似的错误。以下代码用于使用多处理模块运行:
for dd in final_col_dates:
# multiprocessing.Pipe(False)
p = multiprocessing.Process(target=self.ParallelLoopTest, args=(dd, final_col_dates, d1, a, d, final_col_dates_mod, iter, return_list))
jobs.append(p)
p.start()
for proc in jobs:
proc.join()
而且,我面临以下错误追溯:
File "<string>", line 1, in <module>
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\spawn.py", line 106, in spawn_main
exitcode = _main(fd)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\spawn.py", line 116, in _main
self = pickle.load(from_parent)
TypeError: function takes at most 0 arguments (1 given)
Traceback (most recent call last):
File "E:/Projects/Predictive Inbound Cartoon Estimation-MLO/Python/dataprep/DataPrep.py", line 457, in <module>
print(obj.fit())
File "E:/Projects/Predictive Inbound Cartoon Estimation-MLO/Python/dataprep/DataPrep.py", line 39, in fit
return self.__driver__()
File "E:/Projects/Predictive Inbound Cartoon Estimation-MLO/Python/dataprep/DataPrep.py", line 52, in __driver__
final = self.process_()
File "E:/Projects/Predictive Inbound Cartoon Estimation-MLO/Python/dataprep/DataPrep.py", line 135, in process_
sch_dat = self.inline_apply_(all_dates_schd, d1, d2, a)
File "E:/Projects/Predictive Inbound Cartoon Estimation-MLO/Python/dataprep/DataPrep.py", line 297, in inline_apply_
p.start()
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\context.py", line 212, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\context.py", line 313, in _Popen
return Popen(process_obj)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\popen_spawn_win32.py", line 66, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\dkanhar\Anaconda3\lib\multiprocessing\reduction.py", line 59, in dump
ForkingPickler(file, protocol).dump(obj)
BrokenPipeError: [Errno 32] Broken pipe
所以,我尝试取消注释 multiprocessing.Pipe(False)这一行,认为这可能是因为使用了Pipe,我禁用了,但问题仍然存在,我面临同样的错误。
如果有任何帮助,以下是我的方法ParallerLoopTest:
def ParallelLoopTest(self, dd, final_col_dates, d1, a, d, final_col_dates_mod, iter, days_out_vars):
idx1 = final_col_dates.tolist().index(dd)
dataObj = GetPrevDataByDate(d1, a, dd, self.start_hour_of_day)
data2 = dataObj.fit()
dataObj = GetAppointmentControlsSchedule(data2, idx1, d, final_col_dates_mod, dd, self.DC, frgt_typ_filter)
data3 = dataObj.fit()
if idx1 > 0:
data3['APPT_SCHD_ARVL_D_{}'.format(idx1)] = np.nan
print("Iter ", iter)
iter += 1
days_out_vars.append(data3)
我之所以说类似错误的原因是因为如果你看两个错误的Traceback,它们之间都有类似的错误线:
TypeError:从Pickle加载时,函数最多需要0个参数(给定1个),我不知道它为什么会发生。
另请注意,我之前已成功在其他项目中成功实施了这两个模块,但从未遇到过问题,所以我不知道为什么这个问题现在就出现了,这个问题究竟意味着什么。
任何帮助都会非常感激,因为我已经浪费时间来调试这3天了。
由于
在最后一次回答后编辑1
回答后,我试过以下这个。 添加了装饰器 @staticmethod ,删除了self,并使用DataPrep.ParallelLoopTest(args)调用了该方法。
此外,将方法移出类DataPrep,并简单地通过ParallelLoopTest(args)调用,
但在两种情况下,错误都保持不变。
PS:我尝试在两种情况下使用joblib。 所以,两种解决方案都不起作用。
新方法定义:
def ParallelLoopTest(dd, final_col_dates, d1, a, d, final_col_dates_mod, iter, days_out_vars, DC, start_hour):
idx1 = final_col_dates.tolist().index(dd)
dataObj = GetPrevDataByDate(d1, a, dd, start_hour_of_day)
data2 = dataObj.fit()
dataObj = GetAppointmentControlsSchedule(data2, idx1, d, final_col_dates_mod, dd, DC, frgt_typ_filter)
data3 = dataObj.fit()
if idx1 > 0:
data3['APPT_SCHD_ARVL_D_{}'.format(idx1)] = np.nan
print("Iter ", iter)
iter += 1
days_out_vars.append(data3)
编辑2:
我遇到了错误,因为Python无法挑选一些大型数据帧。我的参数/参数中有2个DataFrame,其中一个大约20MB,其他200MB的pickle格式。但那应该不是问题吧?我们应该能够传递Pandas DataFrame。如果我错了,请纠正我。
另外,解决方法是我在使用随机名称调用方法之前将DataFrame保存为csv,传递文件名并读取csv,但这是一个很慢的过程,因为它涉及到大量的csv文件。有什么建议吗?
答案 0 :(得分:0)
在这两种情况下你实际上都得到了完全相同的错误,但是当你在一个例子中使用Pool
(joblib
)而在另一个例子中使用Process
时你得不到主线程中的故障/回溯相同,因为它们不以相同的方式管理过程失败
在这两种情况下,您的过程似乎无法在新的Process
中取消您的子作业。 Pool
给你回复unpickling错误,而使用Process
,你得到一个失败,因为当子进程从这个unpickling错误中死亡时,它会关闭主线程用来写入数据的管道,导致错误在主要过程中。
我的第一个想法是,当您尝试挑选实例方法时会导致错误,而您应该尝试使用静态方法(使用实例方法似乎不正确,因为对象不在进程之间共享)。
在声明@staticmethod
之前使用装饰器ParallelLoopTest
并删除self
参数。
编辑:
另一种可能性是其中一个参数dd, final_col_dates, d1, a, d, final_col_dates_mod, iter, return_list
不能被打开。显然,它来自panda.DataFrame
在这种情况下,我没有看到为什么破坏失败的原因,但我不太了解panda
。
一种解决方法是将数据转储到临时文件中。您可以查看此链接here,以便有效地序列化panda.DataFrame
。另一种解决方案是使用DataFrame.to_pickle
方法和panda.read_pickle
将文件转储/从文件中检索。
请注意,最好将joblib.Parallel
与multiprocessing.Pool
进行比较,而不是与multiprocessing.Process
进行比较。