Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 将值的RDD映射到笛卡尔乘积并按值分组_Scala_Apache Spark - Fatal编程技术网

Scala 将值的RDD映射到笛卡尔乘积并按值分组

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(_).

编辑:我有一个向量集合,并试图计算每个向量与其他向量之间的成对关系。然后我需要对每个向量的结果进行分组。我尝试的方法如下(据我所知,它计算每对2倍):

备选案文1:

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的速度非常快,因为集合可以放入内存中,但对于较大的集合,它显然是一个糟糕的选择

我见过一些类似的问题,例如

我相信其他人也遇到过这个特殊的问题,我真的很感激任何指点!谢谢。

你可以

  • 尝试通过阅读来解决洗牌问题,但我更喜欢其他选项
  • 使用您的选项2,两种解决方案都不能很好地扩展,当集合变大时,两种解决方案都会OOM
  • 与2相同,但将其放在广播变量中,则使用更少的RAM(每个节点1个数据集副本)
  • 问另一个问题,详细说明更高层次的图片,你想做什么,机会你可以完全避免一个carrtesian产品。。。但在你给出背景之前,没有人能帮你展示
  • 关于第3条和我的评论,听起来你有:

    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)))