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

时间:2014-09-12 02:19:26

标签: scala apache-spark

编辑:我有一组向量,我试图计算每个向量与每个其他向量的成对关系。然后我需要将每个向量的结果分组。我尝试的方法如下(我知道它计算每对2x):

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

选项1似乎是自然的选择,但我发现的是即使对于非常小的集合,例如~500个元素,每个元素例如一百个双打的列表,reduceByKey(或groupBy) ,我也尝试过)映射到40000 ShuffleMapTasks,以每秒10次的速度完成。大约30分钟后,大约1/4完成后,作业因GC内存不足错误而失败。有没有办法确保笛卡尔积保留分区?有没有更有效的方法来处理reduce任务?我也尝试过不同的密钥(例如,Ints),但没有任何改进。

选项2对于我的特定情况非常快,因为该集合可以适合内存,但当然对于较大的集合来说它似乎是一个糟糕的选择。

我已经看过一些类似的问题,例如,

https://groups.google.com/forum/#!topic/spark-users/TZla5TnAMTU

Spark: what's the best strategy for joining a 2-tuple-key RDD with single-key RDD?

我确定其他人遇到过这个问题,我真的很感激任何指针!谢谢。

1 个答案:

答案 0 :(得分:2)

你可以

  1. 尝试通过阅读Why does a job fail with "No space left on device", but df says otherwise? 来解决您的随机播放问题,但我更喜欢其他选项
  2. 使用您的选项2, 解决方案都不会很好地扩展,当集合变大时,中的OOM
  3. 与2相同,但是把它放在一个广播变量中,然后用掉更少的RAM(每个节点1个数据集副本)
  4. 提出另一个问题,详细说明你想要做什么的更高级别的图片,你可以完全避免使用carrtesian产品......但是在你提供背景之前没有人可以帮你展示。
  5. 要扩展3和我的评论,听起来像你有:

    val myThings: RDD[MyType] = ...
    

    你想要

    val pairedWithOpResults: RDD[(MyType, MyType, OpResult]
    

    所以我会做(伪代码):

    val myThingsBroadcast = sc.broadcast(myThings.toArray())
    
    myThings.flatMap(thingLeft => myThingsBroadcast.value.map(thingRight => (thingLeft, thingRight, myOp(thingLeft, thingRight)))
    

    如果您想要执行某些groupBy,则需要清楚地解释您想要对每个结果组执行的操作。