我在独立模式下从文本文件加入两个RDD。一个有4亿(9 GB)行,另一个有400万(110 KB)。
3-grams doc1 3-grams doc2
ion - 100772C111 ion - 200772C222
on - 100772C111 gon - 200772C222
n - 100772C111 n - 200772C222
... - .... ... - ....
ion - 3332145654 on - 58898874
mju - 3332145654 mju - 58898874
... - .... ... - ....
在每个文件中,doc编号(doc1或doc2)显示在另一个文件下。由于加入,我希望在docs.e.g。
之间获得一些常见的3克 (100772C111-200772C222,2) --> There two common 3-grams which are 'ion' and ' n'
我运行代码的服务器有128 GB RAM和24个内核。我设置了IntelliJ配置 - 使用-Xmx64G
的VM选项部分这是我的代码:
val conf = new SparkConf().setAppName("abdulhay").setMaster("local[4]").set("spark.shuffle.spill", "true")
.set("spark.shuffle.memoryFraction", "0.6").set("spark.storage.memoryFraction", "0.4")
.set("spark.executor.memory","40g")
.set("spark.driver.memory","40g")
val sc = new SparkContext(conf)
val emp = sc.textFile("\\doc1.txt").map(line => (line.split("\t")(3),line.split("\t")(1))).distinct()
val emp_new = sc.textFile("\\doc2.txt").map(line => (line.split("\t")(3),line.split("\t")(1))).distinct()
val emp_newBC = sc.broadcast(emp_new.groupByKey.collectAsMap)
val joined = emp.mapPartitions(iter => for {
(k, v1) <- iter
v2 <- emp_newBC.value.getOrElse(k, Iterable())
} yield (s"$v1-$v2", 1))
val olsun = joined.reduceByKey((a,b) => a+b)
olsun.map(x => x._1 + "\t" + x._2).saveAsTextFile("...\\out.txt")
如图所示,在使用广播变量的连接过程中,我的键值会发生变化。所以我似乎需要重新分配连接的值?它非常昂贵。结果,我结束了太多的溢出问题,它从未结束。我认为128 GB内存必须足够。据我所知,当使用广播变量时,洗牌正在显着减少?那我的申请有什么问题?
提前致谢。
编辑:
我也尝试过spark的连接功能,如下所示:
var joinRDD = emp.join(emp_new);
val kkk = joinRDD.map(line => (line._2,1)).reduceByKey((a, b) => a + b)
再次结束了太多的溢出。
EDIT2:
val conf = new SparkConf().setAppName("abdulhay").setMaster("local[12]").set("spark.shuffle.spill", "true")
.set("spark.shuffle.memoryFraction", "0.4").set("spark.storage.memoryFraction", "0.6")
.set("spark.executor.memory","50g")
.set("spark.driver.memory","50g")
val sc = new SparkContext(conf)
val emp = sc.textFile("S:\\Staff_files\\Mehmet\\Projects\\SPARK - scala\\wos14.txt").map{line => val s = line.split("\t"); (s(5),s(0))}//.distinct()
val emp_new = sc.textFile("S:\\Staff_files\\Mehmet\\Projects\\SPARK - scala\\fwo_word.txt").map{line => val s = line.split("\t"); (s(3),s(1))}//.distinct()
val cog = emp_new.cogroup(emp)
val skk = cog.flatMap {
case (key: String, (l1: Iterable[String], l2: Iterable[String])) =>
(l1.toSeq ++ l2.toSeq).combinations(2).map { case Seq(x, y) => if (x < y) ((x, y),1) else ((y, x),1) }.toList
}
val com = skk.countByKey()
答案 0 :(得分:1)
我不会使用广播变量。当你说:
val emp_newBC = sc.broadcast(emp_new.groupByKey.collectAsMap)
Spark首先将ENTIRE数据集移动到主节点,这是一个巨大的瓶颈,容易在主节点上产生内存错误。然后,这块内存被拖回到所有节点(大量网络开销),也会产生内存问题。
相反,请使用join
加入RDD(请参阅说明here)
如果钥匙太少,也要弄清楚。对于加入Spark,基本上需要将整个密钥加载到内存中,如果你的密钥太少,对任何给定的执行程序来说可能仍然是一个太大的分区。
另外注意:reduceByKey
无论如何都会重新分配。
编辑:---------------------
好的,鉴于澄清,并假设每个文档#3克的数量不是太大,这就是我要做的:
cogroup
两个RDD,它们可以获得3gram密钥和2个doc#列表coutByKey
或countByKeyAprox
以计算每个文档对的不同3克数。注意:您可以跳过此.distinct()
来电。此外,您不应该将每一行拆分两次。更改line => (line.split("\t")(3),line.split("\t")(1)))
line => { val s = line.split("\t"); (s(3),s(1)))
编辑2:
你似乎也在严重调整记忆力。例如,使用.set("spark.shuffle.memoryFraction", "0.4").set("spark.storage.memoryFraction", "0.6")
基本上没有任务用于执行任务(因为它们总计为1.0)。我本应该早点看到这个问题本身。
此外,如果您在一台计算机上运行它,您可能会尝试使用单个巨大的执行程序(甚至完全忽略Spark),因为您不需要分布式处理平台的开销(以及分布式硬件容错等)。