繁体   English   中英

在Apache Spark中,我可以轻松地重复/嵌套一个SparkContext.parallelize吗?

[英]In Apache Spark, can I easily repeat/nest a SparkContext.parallelize?

我正在尝试为我们试图解决的遗传问题建模,并逐步加以解决。 我可以从Spark示例成功运行PiAverage示例。 该示例将一个圆圈“掷飞镖”(在本例中为10 ^ 6),并计算“落在圆圈中”的数量以估算PI

假设我要重复该过程1000次(并行),并对所有这些估计求平均值。 我正在尝试寻找最好的方法,似乎会有两个调用要并行化? 嵌套通话? 有没有办法将地图链接或减少通话数量? 我看不到

我想知道类似以下想法的智慧。 我想到了使用累加器跟踪结果估计。 jsc是我的SparkContext,单次运行的完整代码在问题末尾,谢谢您的投入!

Accumulator<Double> accum = jsc.accumulator(0.0);

// make a list 1000 long to pass to parallelize (no for loops in Spark, right?)
List<Integer> numberOfEstimates = new ArrayList<Integer>(HOW_MANY_ESTIMATES);

// pass this "dummy list" to parallelize, which then 
// calls a pieceOfPI method to produce each individual estimate  
// accumulating the estimates. PieceOfPI would contain a 
// parallelize call too with the individual test in the code at the end
jsc.parallelize(numberOfEstimates).foreach(accum.add(pieceOfPI(jsc, numList, slices, HOW_MANY_ESTIMATES)));

// get the value of the total of PI estimates and print their average
double totalPi = accum.value();

// output the average of averages
System.out.println("The average of " + HOW_MANY_ESTIMATES + " estimates of Pi is " + totalPi / HOW_MANY_ESTIMATES);

我在SO上看到的矩阵或其他答案似乎没有给出该特定问题的答案,我进行了几次搜索,但是如果不“并行化并行化”,我将看不到如何做到这一点。 那是个坏主意吗?

(是的,我在数学上意识到我可以做更多的估算并有效地获得相同的结果:)试图建立老板想要的结构,再次感谢!

如果没有帮助,我将整个测试程序放在这里,如果没有,我正在测试一个累加器。 其核心将成为PieceOfPI():

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.spark.Accumulable;
import org.apache.spark.Accumulator;
import org.apache.spark.SparkContext;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.storage.StorageLevel;
import org.apache.spark.SparkConf;
import org.apache.spark.storage.StorageLevel;

public class PiAverage implements Serializable {

public static void main(String[] args) {

    PiAverage pa = new PiAverage();
    pa.go();

}

public void go() {

    // should make a parameter like all these finals should be
    // int slices = (args.length == 1) ? Integer.parseInt(args[0]) : 2;
    final int SLICES = 16;

    // how many "darts" are thrown at the circle to get one single Pi estimate
    final int HOW_MANY_DARTS = 1000000;

    // how many "dartboards" to collect to average the Pi estimate, which we hope converges on the real Pi
    final int HOW_MANY_ESTIMATES = 1000;

    SparkConf sparkConf = new SparkConf().setAppName("PiAverage")
        .setMaster("local[4]");

    JavaSparkContext jsc = new JavaSparkContext(sparkConf);

    // setup "dummy" ArrayList of size HOW_MANY_DARTS -- how many darts to throw
    List<Integer> throwsList = new ArrayList<Integer>(HOW_MANY_DARTS);
    for (int i = 0; i < HOW_MANY_DARTS; i++) {
        throwsList.add(i);
    }

    // setup "dummy" ArrayList of size HOW_MANY_ESTIMATES
    List<Integer> numberOfEstimates = new ArrayList<Integer>(HOW_MANY_ESTIMATES);
    for (int i = 0; i < HOW_MANY_ESTIMATES; i++) {
        numberOfEstimates.add(i);
    }

    JavaRDD<Integer> dataSet = jsc.parallelize(throwsList, SLICES);

    long totalPi = dataSet.filter(new Function<Integer, Boolean>() {
        public Boolean call(Integer i) {
            double x = Math.random();
            double y = Math.random();
            if (x * x + y * y < 1) {
                return true;
            } else
                return false;
        }
    }).count();

    System.out.println(
            "The average of " + HOW_MANY_DARTS + " estimates of Pi is " + 4 * totalPi / (double)HOW_MANY_DARTS);

    jsc.stop();
    jsc.close();
}
}

让我从您的“背景问题”开始。 诸如mapjoingroupBy等转换操作分为两类: 那些需要从所有分区中输入数据进行洗牌的企业,而那些不需要。 诸如groupByjoin类的操作需要groupBy ,因为您需要使用相同的键(考虑SQL JOINGROUP BY操作的工作方式)将所有RDD分区中的所有记录汇总在一起。 另一方面, mapflatMapfilter等不需要改组,因为该操作在上一步分区的输入上可以正常工作。 它们一次只能处理单个记录,而不是具有匹配键的一组记录。 因此,不需要改组。

要了解“额外地图”没有明显的开销,此背景是必需的。 诸如mapflatMap等之类的一系列操作被一起“压缩”为一个“阶段”(当您在Spark Web控制台中查看作业的详细信息时将显示该阶段),以便仅实现一个RDD,而一个RDD实现阶段的结束。

关于您的第一个问题。 我不会为此使用累加器。 它们用于“边带”数据,例如计算您解析的坏行数。 在此示例中,作为示例,您可以使用累加器计算在1半径范围内与在1半径范围内的(x,y)对。

Spark发行版中的JavaPiSpark示例与它取得的效果JavaPiSpark 您应该研究它为什么起作用。 这是大数据系统的正确数据流模型。 您可以使用“聚合器”。 Javadocs中 ,单击“索引”,并期待在aggaggregateaggregateByKey功能。 但是,它们不再是可以理解的,在这里也没有必要。 它们提供的灵活性比map然后reduce更大,因此值得一读。

代码的问题在于,您实际上是在试图告诉Spark该怎么做,而不是表达您的意图并让Spark优化它为您执行的方式。

最后,我建议您购买和研究O'Reilly的“ Learning Spark”。 它很好地解释了内部细节(例如暂存),并显示了许多示例代码,您也可以使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM