parallelization level of Tupled RDD data
假设我有一个如下类型的 RDD:
1
| RDD[(Long, List(Integer))] |
我可以假设整个列表都位于同一个工人吗?我想知道某些操作在 RDD 级别是否可以接受还是应该在驱动程序中计算。例如:
1
| val data : RDD [(Long, List (Integer ))] = someFunction () //creates list for each timeslot |
请注意,List 可能是 aggregate 或任何其他操作的结果,不一定是作为一个整体创建的。
1 2 3 4 5 6
| val diffFromMax = data. map(item => (item. _1, findDiffFromMax (item. _2 )))
def findDiffFromMax (data : List [Integer ]): List [Integer ] = {
val maxItem = data. max
data. map(item => (maxItem - item ))
} |
问题是 List 是分布式计算 maxItem 可能会导致大量网络流量。这可以使用以下类型的 RDD 处理:
1
| RDD[(Long, Integer /*Max Item*/,List(Integer))] |
最大项目是在驱动程序处计算的。
所以问题(实际上是 2 个问题)是:
在 RDD 数据的哪个点我可以假设数据位于一名工人? (参考文档或个人评估的答案会很棒)如果有的话?在 Tuple: ((Long, Integer), Double) 中的 Tuple 的情况下会发生什么?
使用元组设计算法的常见做法是什么?我是否应该始终将数据视为可能出现在不同的工人身上?我应该总是在第一个元组字段将它分解为最小粒度 - 对于在时间段(长)中有用户(字符串)的数据(双)的情况 - 数据应该是(长,(强,双))还是((Long, String), Double) 或者 (String, (Long, Double))?或者这可能不是最优的,矩阵更好?
简短的回答是肯定的,您的列表将位于一个工人中。
您的元组是 RDD 中的单个记录。单个记录始终位于单个分区(将位于单个工作人员上)。
当您执行 findDiffFromMax 时,您是在目标 worker 上运行它(因此该函数被序列化为所有要运行的 worker)。
您应该注意的是,当您生成 (k,v) 元组时,通常这意味着一个键值对,因此您可以在 RDD 上执行基于键的操作。顺序 ((Long, (Strong, Double)) 与 ((Long, String), Double) 或任何其他方式) 并不重要,因为它都是单个记录。唯一重要的是哪个是关键操作的关键,所以问题将是你的计算逻辑
- 谢谢你的解释。如果不是 List 而是 ParArray 怎么办?没关系,因为它仍然在作为单个记录的元组中?如果我的情况是 RDD[ParArray[(Long, Integer)]] 每个 ParArray 会是一条记录吗?
-
另一个问题是由于它的键值对,我可以说元组中具有相同第一个元素的所有元组都将位于一起吗?我的意思是我可以在不重新洗牌的情况下使用 join 吗?
-
在这方面,RDD 被定义为 RDD[T],其中 T 是记录类型,并且记录始终位于单个分区中。如果您选择 T 为 ParArray[(Long, Integer) 那么它将是一条记录。当然,如果记录太大,您可能只会遇到 OOM 异常或类似问题,所以不要过度使用。
-
托达的解释。
-
当您开始时,没有明确的相关性。如果您使用 GroupByKey,则该键的所有元素都将出现在单个分区中。如果您执行 reduceByKey,则减少将发生在每个分区中,然后结果将合并到最终分区中。