如何并行化几个apache spark rdds?

时间:2015-04-22 03:13:06

标签: scala apache-spark apache-spark-sql

我有下一个代码:

sc.parquetFile("some large parquet file with bc").registerTempTable("bcs")
sc.parquetFile("some large parquet file with imps").registerTempTable("imps")
val bcs = sc.sql("select * from bcs")
val imps = sc.sql("select * from imps")

我想这样做:

bcs.map(x => wrapBC(x)).collect
imps.map(x => wrapIMP(x)).collect

但是当我这样做时,它不会运行异步。我可以用Future做这件事:

val bcsFuture = Future { bcs.map(x => wrapBC(x)).collect }
val impsFuture = Future { imps.map(x => wrapIMP(x)).collect }
val result = for {
  bcs <- bcsFuture
  imps <- impsFuture
} yield (bcs, imps)
Await.result(result, Duration.Inf) //this return (Array[Bc], Array[Imp])

我想在没有未来的情况下这样做,我该怎么做?

3 个答案:

答案 0 :(得分:2)

更新这最初是在问题更新之前编写的。鉴于这些更新,我同意@stholzm's answer在这种情况下使用cartesian


确实存在有限数量的操作,这些操作将为FutureAction[A]生成RDD[A]并在后台执行。这些内容在AsyncRDDActions上提供,只要您导入SparkContext._,任何RDD都可以根据需要隐式转换为AysnchRDDAction。对于您的特定代码示例:

bcs.map(x => wrapBC(x)).collectAsync
imps.map(x => wrapIMP(x)).collectAsync

除了在背景中评估DAG到行动之外,生成的FutureAction还有cancel方法来尝试提前结束处理。

买者

这可能与您的想法无关。如果目的是从两个来源获取数据然后合并它们,您更有可能想要加入或分组RDD 。为此,您可以查看PairRDDFunctions中可用的函数,通过隐式转换再次在RDD上可用。

如果目的不是让数据图表进行交互,那么根据我的经验,然后同时运行批处理可能只会减慢两者的速度,尽管这可能是集群配置的结果。如果资源管理器被设置为以FIFO顺序对集群进行垄断(独立和YARN模式中的默认值,我相信;我对Mesos不确定)那么每个异步收集都会争用为了这种垄断,彼此执行任务,然后再次争夺下一个执行阶段。

将此与使用Future来阻止对下游服务或数据库的阻塞调用进行比较,例如,所讨论的资源是完全独立的,或者通常具有足够的资源容量来并行处理多个请求而不会发生争用。

答案 1 :(得分:1)

更新:我误解了这个问题。期望的结果不是笛卡儿积Array[(Bc, Imp)]

但是我认为单map次调用需要多长时间并不重要,因为只要你添加其他转换,Spark就会尝试以有效的方式组合它们。只要您只在RDD上链接转换,数据就不会发生任何变化。当您最终应用操作时,执行引擎将找到生成所请求数据的方法。

所以我的建议是不要过多考虑中间步骤并尽可能避免collect,因为它会将所有数据提取到驱动程序中。


您似乎正在自己制作笛卡尔产品。请尝试cartesian

val bc = bcs.map(x => wrapBC(x))
val imp = imps.map(x => wrapIMP(x))
val result = bc.cartesian(imp).collect

请注意,collect在最终RDD上调用,不再在中间结果上调用。

答案 2 :(得分:0)

您可以使用$html_string = '<!-- start block --> <p>Hello world etc</p> <div>something</div> <div>something2</div> <!-- end of block --> <div>something3</div> '; $html = str_get_html($html_string); // start point $start = $html->find('*'); $output = ''; $go = false; foreach($start as $e) { if($e->innertext === '<!-- start block -->') { $go = true; continue; } elseif($e->innertext === '<!-- end of block -->') { break; } if($go) { $output .= $e; } } echo $output; 来解决此问题。例如:

union

如果要使用sortBy或其他操作,可以使用trait或main类的继承。