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