MultiProcessing中的类似错误。函数

时间:2016-10-12 07:59:31

标签: python multiprocessing pickle joblib

我找不到更好的方法来描述我所面临的错误,但是每当我尝试将多处理实现为循环调用时,这个错误似乎都会出现。

我已经同时使用了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文件。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

在这两种情况下你实际上都得到了完全相同的错误,但是当你在一个例子中使用Pooljoblib)而在另一个例子中使用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.Parallelmultiprocessing.Pool进行比较,而不是与multiprocessing.Process进行比较。