是否可以在Python中广播RDD?
我正在关注这本书"高级分析与Spark:从大规模数据学习模式"在第3章中,需要广播RDD。我试图使用Python而不是Scala来跟踪这些示例。
无论如何,即使有这个简单的例子我也有错误:
my_list = ["a", "d", "c", "b"]
my_list_rdd = sc.parallelize(my_list)
sc.broadcast(my_list_rdd)
错误是:
"It appears that you are attempting to broadcast an RDD or reference an RDD from an "
Exception: It appears that you are attempting to broadcast an RDD or reference an RDD from an
action or transformation. RDD transformations and actions can only be invoked by the driver, n
ot inside of other transformations; for example, rdd1.map(lambda x: rdd2.values.count() * x) i
s invalid because the values transformation and count action cannot be performed inside of the
rdd1.map transformation. For more information, see SPARK-5063.
我真的不明白"行动或转型"错误是指。
我正在使用spark-2.1.1-hadoop2.7
。
重要编辑:这本书是正确的。我只是没有读到它不是正在广播的RDD,而是使用collectAsMap()获得的地图版本。
谢谢!
答案 0 :(得分:3)
是否可以在Python中广播RDD?
TL; DR 否。
当你认为RDD 真正是什么时,你会发现它根本不可能。您可以播放的RDD中没有任何内容。它也是脆弱的(可以这么说)。
RDD是描述某些数据集上的分布式计算的数据结构。通过RDD的功能,您可以描述计算内容和方式。它是一个抽象的实体。
引用RDD的scaladoc:
表示可以并行操作的不可变分区元素集合
在内部,每个RDD都有五个主要属性:
分区列表
计算每个分割的功能
其他RDD的依赖关系列表
可选地,键值RDD的分区器(例如,说RDD是散列分区的)
(可选)计算每个拆分的首选位置列表(例如HDFS文件的块位置)
你可以播放的内容不多(引用SparkContext.broadcast方法的scaladoc):
broadcast [T](值:T)(隐式arg0:ClassTag [T]):Broadcast [T] 向群集广播只读变量,返回
org.apache.spark.broadcast.Broadcast
用于在分布式函数中读取它的对象。该变量将仅发送到每个集群一次。
您只能广播实际值,但RDD只是一个容器值,只有在执行者处理其数据时才可用。
广播变量允许程序员在每台机器上保留一个只读变量,而不是随副本一起发送它的副本。例如,它们可用于以有效的方式为每个节点提供大型输入数据集的副本。
后来在同一份文件中:
这意味着显式创建广播变量仅在跨多个阶段的任务需要相同数据或以反序列化形式缓存数据时非常有用。
然而,您可以[{1}} RDD 拥有的数据集,并按如下方式广播:
collect
在"收集数据集"步骤,数据集离开RDD空间并成为本地可用的集合,即Python值,然后可以广播。
答案 1 :(得分:0)
你无法播放RDD。您在处理RDD时多次使用的所有执行程序节点上广播值。因此,在您的代码中,您应该在广播之前收集您的RDD。 collect
将RDD
转换为本地python对象,可以毫无问题地进行广播。
sc.broadcast(my_list_rdd.collect())
当您广播某个值时,该值将被序列化并通过网络发送到所有执行程序节点。您的my_list_rdd
只是对分布在多个节点上的RDD的引用。序列化此引用并将此引用广播到所有工作节点并不意味着工作节点中的任何内容。所以你应该收集你的RDD的值并改为广播这个值。
可以找到有关Spark Broadcast的更多信息here
注意:如果您的RDD太大,应用程序可能会遇到OutOfMemory错误。 collect
方法将所有数据拉入驱动程序通常不够大的内存中。