Scala 将值的RDD映射到笛卡尔乘积并按值分组
编辑:我有一个向量集合,并试图计算每个向量与其他向量之间的成对关系。然后我需要对每个向量的结果进行分组。我尝试的方法如下(据我所知,它计算每对2倍): 备选案文1:Scala 将值的RDD映射到笛卡尔乘积并按值分组,scala,apache-spark,Scala,Apache Spark,编辑:我有一个向量集合,并试图计算每个向量与其他向量之间的成对关系。然后我需要对每个向量的结果进行分组。我尝试的方法如下(据我所知,它计算每对2倍): 备选案文1: val myRDD: RDD[MyType] val grouped: RDD[(MyType, List[MyVector])] = myRDD.cartesian(myRDD) .mapValues(List(_)) .reduceByKey( (x,y) => x:::y ) // or groupBy(_).
val myRDD: RDD[MyType]
val grouped: RDD[(MyType, List[MyVector])] = myRDD.cartesian(myRDD)
.mapValues(List(_))
.reduceByKey( (x,y) => x:::y ) // or groupBy(_).mapValues(_.toList)
备选案文2:
val items: Array[MyType] = for (row <- myRDD.collect) yield row
val grouped: RDD[(MyType, List[MyVector])] = myRDD.map(x => (x, items.map(y => (x, y)).toList))
val items:Array[MyType]=for(行(x,items.map(y=>(x,y)).toList))
选项1似乎是自然选择,但我发现即使是非常小的集合,例如约500个元素,例如每个元素有100个双倍的列表,reduceByKey(或groupBy,我也尝试过)映射到40000个ShuffleMaptask,以每秒10个左右的速度完成。大约30分钟后,大约完成1/4时,作业失败,并出现GC内存不足错误。有没有办法确保笛卡尔积保留分区?有没有更有效的方法来处理reduce任务?我也尝试过不同的键(例如int),但没有任何改进
对于我的特殊情况,选项2的速度非常快,因为集合可以放入内存中,但对于较大的集合,它显然是一个糟糕的选择
我见过一些类似的问题,例如
我相信其他人也遇到过这个特殊的问题,我真的很感激任何指点!谢谢。你可以
val myThings: RDD[MyType] = ...
你想要什么
val pairedWithOpResults: RDD[(MyType, MyType, OpResult]
所以我会做(伪代码):
如果你想执行一些分组,你需要清楚地解释你想对每个结果组做什么。Sam,谢谢你的回答。正如我在编辑中详细介绍的,这个特定问题的更大背景是对集合中的每对向量进行两两计算。不过,一般来说,我需要执行其他groupBy操作,这些操作不是简单的聚合,其中键的数量与记录的数量相同。*也就是说,进行两两计算,然后将每个向量的结果与每个其他向量分组。@y2s(我已更新为包含广播变量)。我还是有点挑剔,听起来这些东西都是向量并不重要。。。我来说说我的意思谢谢Sam我也一直在考虑广播变量。如果RDD太大,无法收集和广播,那么将其分块或以其他方式流式传输并广播是否合理?事实上,这些类型是类似向量的,这是部分相关的,因为在某些情况下,我希望对每个列表进行计算(例如,计算距离,如KNN、汇总统计等)。(旁白:中有一个有趣的关于成对余弦距离的PR)我们处理巨大BVs的方法是在一个节点上停止一个工作者,并将该节点用于驱动程序(给驱动程序进程大量RAM)。这意味着您必须牺牲一个节点:/但是比使用BVs序列/流更好。。。如果有一种方法可以将工作进程作为驱动程序重用,那就太好了。为什么需要对每个向量的结果进行分组???为什么这些东西是向量?我认为您在将问题与不必要的信息混淆时漏掉了一些重要信息,因为这个问题很神秘。很抱歉,我打扰了您,但我在尝试使用由我定义的类型时遇到了一个问题。在本例中,它不起作用,而对于默认的java类型,它的作用就像一个符咒。你知道我的问题的原因吗?感谢我在一条旧注释@mark91上花了两分钱。如果某些东西在Java标准类上有效,但在您的类上无效,那么它们可能无法实现正确的Spark函数,它们还需要实现可序列化,这只是一个想法
val myThingsBroadcast = sc.broadcast(myThings.toArray())
myThings.flatMap(thingLeft => myThingsBroadcast.value.map(thingRight => (thingLeft, thingRight, myOp(thingLeft, thingRight)))