【问题标题】:Efficiently consolidate results of concurrent.futures parallel execution?高效合并 concurrent.futures 并行执行的结果?
【发布时间】:2018-10-30 15:44:54
【问题描述】:

我有一个大约 100M 行的 pandas 数据框。并行处理在多核机器上运行良好,每个核的利用率为 100%。但是,executor.map() 的结果是一个生成器,因此为了实际收集处理后的结果,我遍历该生成器。这非常非常慢(几个小时),部分原因是它是单核,部分原因是循环。其实比my_function()中实际处理要慢很多

有没有更好的方法(可能是并发的和/或矢量化的)?

编辑:在 Python 3.7.0 中使用 pandas 0.23.4(目前最新)

import concurrent
import pandas as pd

df = pd.DataFrame({'col1': [], 'col2': [], 'col3': []})

with concurrent.futures.ProcessPoolExecutor() as executor:
    gen = executor.map(my_function, list_of_values, chunksize=1000)

# the following is single-threaded and also very slow
for x in gen:
    df = pd.concat([df, x])  # anything better than doing this?
return df

【问题讨论】:

  • 我认为只有pd.concat(gen) 会起作用并且应该更快,尽管总体上这可能仍然相当慢。
  • 我试过了(请参阅 Sraw 答案的评论),但不支持。
  • 你为什么还在对concat的调用中加入df。它应该只是df = pd.concat(gen)
  • 哦,我们将这些附加到现有的 df。你是对的,这里不需要这个问题,我现在就试试。
  • 感谢@ALollz,效果很好。

标签: python pandas concurrency parallel-processing


【解决方案1】:

这是与您的案例相关的基准:https://stackoverflow.com/a/31713471/5588279

如您所见, concat(append) 多次是非常低效的。你应该做pd.concat(gen)。我相信底层实现会预先分配所有需要的内存。

在你的情况下,内存分配每次都完成。

【讨论】:

  • 我尝试了pd.concat([df, gen]),但得到了TypeError: cannot concatenate object of type "<class 'generator'>"; only pd.Series, pd.DataFrame, and pd.Panel (deprecated) objs are valid。这基本上是问题的症结所在,是否存在这样的事情。
  • @wishihadabettername 尝试先将其转换为列表。
  • 成功了; list() 毕竟不需要,但我必须分两个阶段完成,首先将生成器转换为自己的数据帧df2 = pd.concat(gen),然后将其与现有数据帧df_final = pd.concat([df, df2]) 连接。第二步不在基本问题范围内,但出现在问题中,所以我在这里明确表示。谢谢@Sraw 和@ALoltz。
  • 是的,我认为它应该可以在不转换的情况下工作。而且我相信它现在更快了?
  • 是的,更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多