我的问题:我有一个模型引擎,它接受一个参数配置列表,并计算一个与该配置相关的指标对应的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''。它现在确实有意义,因为启动驱动程序并将罐子移动到工作人员有一些开销。