为什么我的Spark驱动程序如此之慢?

时间:2017-08-07 15:38:11

标签: java apache-spark optimization

我的问题:我有一个模型引擎,它接受一个参数配置列表,并计算一个与该配置相关的指标对应的double值。我有六个参数,每个参数都可以根据列表而变化。我想通过蛮力找到最佳参数配置,考虑组合将产生更高的输出指标值。由于我正在学习Spark,我意识到通过笛卡尔积运算,我可以轻松生成组合,并将RDD拆分为并行处理。所以,我想出了这个驱动程序:

public static void main(String[] args) {

    String scriptName = "model.mry";

    String scriptStr = null;

    try {
        scriptStr = new String(Files.readAllBytes(Paths.get(scriptName)));
    } catch (IOException ex) {
        Logger.getLogger(BruteForceDriver.class.getName()).log(Level.SEVERE, null, ex);
        System.exit(1);
    }

    final String script = scriptStr;

    SparkConf conf = new SparkConf()
            .setAppName("wordCount")
            .setSparkHome("/home/danilo/bin/spark-2.2.0-bin-hadoop2.7")
            .setJars(new String[]{"/home/danilo/NetBeansProjects/SparkHello1/target/SparkHello1-1.0.jar",
        "/home/danilo/.m2/repository/org/modcs/mercury/4.7/mercury-4.7.jar"})
            .setMaster("spark://danilo-desktop:7077");

    String baseDir = "/home/danilo/NetBeansProjects/SimulationOptimization/workspace/";

    JavaSparkContext sc = new JavaSparkContext(conf);

    final int NUM_SERVICES = 6;
    final int QTD = 3;

    JavaRDD<Service>[] providers = new JavaRDD[NUM_SERVICES];

    for (int i = 1; i <= NUM_SERVICES; i++) {
        providers[i - 1] = sc.textFile(baseDir + "provider"
                + i
                + ".mat")
                .filter((t1) -> !t1.contains("#") && !t1.trim().isEmpty())
                .map(Service.createParser("" + i))
                .zipWithIndex().filter((t1) -> {
                    return t1._2 < QTD;
                }).keys();
    }

    JavaPairRDD c = null;
    JavaRDD<Service> p = providers[0];

    for (int i = 1; i < NUM_SERVICES; i++) {
        if (c == null) {
            c = p.cartesian(providers[i]);
        } else {
            c = c.cartesian(providers[i]);
        }
    }

    JavaRDD<List<Service>> cartesian = c.map(new FlattenTuple<>());

    final Broadcast<ModelEvaluator> model = sc.broadcast(new ModelEvaluator(script));

    JavaPairRDD<Double, List<Service>> results = cartesian.mapToPair(
            (t) -> {
                try {
                    double val = model.value().evaluateModel(t);
                    System.out.println(val);
                    return new Tuple2<>(val, t);
                } catch (Exception ex) {
                    return null;
                }
            }
    );

    results.sortByKey().collect().forEach((t) -> {
        System.out.println(t._1 + ", " + t._2);
    });

    sc.close();
}

“QTD”变量允许我控制每个参数变化的间隔大小。对于QTD = 3,我将有3 ^ 6 = 729种组合。问题是计算所有这些组合需要很长时间。我只使用普通的Java线程编写了一个实现,运行时间大约是40秒。使用我的Spark驱动程序,运行时间超过6分钟。为什么我的Spark程序与普通的Java多线程程序相比这么慢?

修改

我说:

results = results.cache();

在排序结果之前,现在运行时间为2.5分钟。

编辑2

我手工创建了一个带有参数的笛卡尔积的RDD,而不是使用框架提供的操作。现在我的运行时间是1'25''。它现在确实有意义,因为启动驱动程序并将罐子移动到工作人员有一些开销。

0 个答案:

没有答案