我有一个非常大的数据帧,我想做一些计算,所以我做了一个multiprocessing.map并将数据帧设置为全局。但是,这是否意味着对于每个进程,程序将单独复制数据帧(因此它将比共享数据帧快)?
答案 0 :(得分:1)
如果我理解正确,您可以尝试在Pandas DataFrame上使用 multiprocessing.map ,从而获得任何好处,因为DataFrame是在NumPy ndarray结构上构建的和 NumPy 已经发布GIL,扩展到SMP硬件,使用矢量化的机器指令,等等。
正如您所说,您可能会在DataFrame结构上产生大量RAM消耗和数据复制或共享内存锁定开销,这些都没有任何好处。关于NumPy和Python的multiprocessing模块组合的性能考虑在此SO Question: Multiprocessing.Pool makes Numpy matrix multiplication slower中进行了讨论。
您将此DataFrame视为只读这一事实很有意思,因为它建议您可以围绕 os.fork() 编写代码,由于操作系统CoW(副本) -on-write)通过 fork()系统调用的语义,应该是一种与子进程共享数据的廉价方式,允许每个人以各种方式分析日期。 (当然,任何写入数据的代码都会触发新页面的分配和复制。)
多处理模块正在使用 fork()系统调用(至少在Unix,Linux和类似系统上)。如果在调用任何多处理函数或实例化其创建子进程的任何对象之前创建并完全填充此大型数据结构(DataFrame),则可能能够访问DataFrame的副本每个进程隐式继承。我现在没有时间编写一些测试代码;但这可能有用。
至于将结果整合回某个父进程或委托进程......您可以通过任何IPC(进程间通信)机制来实现。如果您能够在调用任何多处理分叉方法之前通过初始化来隐式共享数据,那么您可以简单地实例化multiprocessing.Queue并通过它提供结果。如果做不到这一点,我个人只考虑在同一系统或该LAN网段上的任何其他系统上设置Redis的实例。通过API和Python模块(具有hiredis的自动/透明支持,Redis结果的高性能反序列化),Redis非常高效且极易配置和维护。
如果您的需求带您朝这个方向发展,Redis可能还可以让您更轻松地跨多个节点分发您的应用程序。当然,到那时您可能还在考虑使用PySpark,它可以提供许多功能,这些功能可以很好地映射到Pandas DataFrames到Apache Spark RDD集(或Spark SQL" DataFrames&#34 )。这是几年前的一篇文章:Databricks: From Pandas to Apache Spark's DataFrames。
一般而言,Apache Spark的重点是在不同节点之间分配数据计算;这比在单个机器中跨核心分布它们本质上更具可扩展性。 (然后,问题归结为节点的I / O,因此每个节点都可以加载数据集的块。这是一个非常适合HDFS的问题。
我希望有所帮助。
答案 1 :(得分:0)
每个子流程都有自己的资源,所以这意味着。更确切地说,每个子流程都将复制原始数据帧的一部分,由您的实现决定。
但它会比分享快吗?我不确定。除非您的数据框架实现w / r锁定,否则读取共享锁定或读取分开的锁定是相同的。但为什么数据帧需要锁定读操作?这没有意义。