Scala 减少Apache spark作业/应用程序的运行时间

Scala 减少Apache spark作业/应用程序的运行时间,scala,apache-spark,apache-spark-ml,Scala,Apache Spark,Apache Spark Ml,我们正在尝试实现一个简单的spark作业,它读取一个CSV文件(1行数据),并使用预先构建的随机森林模型对象进行预测。此作业不包括任何数据预处理或数据操作 我们以独立模式运行spark,应用程序在本地运行。配置如下: 内存:8GB 内存:40GB 芯数:2 Spark版本:1.5.2 Scala版本:2.10.5 输入文件大小:1KB(1行数据) 模型文件大小:1595 KB(400棵树随机森林) 目前,spark submit中的实现大约需要13秒。然而,运行时是这个应用程序的一个巨大问题 有

我们正在尝试实现一个简单的spark作业,它读取一个CSV文件(1行数据),并使用预先构建的随机森林模型对象进行预测。此作业不包括任何数据预处理或数据操作

我们以独立模式运行spark,应用程序在本地运行。配置如下: 内存:8GB 内存:40GB 芯数:2 Spark版本:1.5.2 Scala版本:2.10.5 输入文件大小:1KB(1行数据) 模型文件大小:1595 KB(400棵树随机森林)

目前,spark submit中的实现大约需要13秒。然而,运行时是这个应用程序的一个巨大问题

  • 有没有办法优化代码,使运行时间缩短到1秒或2秒?(高度优先)

  • 我们注意到,实际代码的执行大约需要7-8秒,而启动和设置上下文大约需要5-6秒,因此有没有一种方法可以在运行spark submit时保持spark上下文的运行

  • 这是应用程序代码

    import org.apache.spark.SparkContext
    import org.apache.spark.SparkContext._
    import org.apache.spark.SparkConf
    
    object RF_model_App {
      def main(args: Array[String]) {
    
    val conf = new SparkConf().setAppName("Simple Application")
    val sc = new SparkContext(conf)
    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
    import org.apache.spark.ml.Pipeline
    import org.apache.spark.ml.feature4.{RandomForestfeature4Model, RandomForestClassifier}
    import org.apache.spark.ml.evaluation.Multiclassfeature4Evaluator
    import org.apache.spark.ml.feature.{IndexToString, StringIndexer, VectorIndexer}
    import org.apache.spark.sql.functions.udf
    import org.apache.spark.ml.feature.VectorAssembler
    import org.apache.spark.ml.feature.StringIndexer
    import sqlContext.implicits._
    val Test = sqlContext.read.format("com.databricks.spark.csv").option("header","true").load("/home/ubuntu/Test.csv")
    Test.registerTempTable("Test")
    val model_L1 = sc.objectFile[RandomForestfeature4Model]("/home/ubuntu/RF_L1.model").first()
    
    val toInt = udf[Int, String]( _.toInt)
    val toDouble = udf[Double, String]( _.toDouble)
    val featureDf = Test.withColumn("id1", toInt(Test("id1")))  .withColumn("id2", toInt(Test("id2")))  .withColumn("id3", toInt(Test("id3")))  .withColumn("id4", toInt(Test("id4")))   .withColumn("feature3", toInt(Test("feature3")))   .withColumn("feature9", toInt(Test("feature9")))    .withColumn("feature10", toInt(Test("feature10")))  .withColumn("feature12", toInt(Test("feature12")))  .withColumn("feature14", toDouble(Test("feature14")))   .withColumn("feature15", toDouble(Test("feature15")))   .withColumn("feature16", toInt(Test("feature16")))  .withColumn("feature17", toDouble(Test("feature17")))   .withColumn("feature18", toInt(Test("feature18")))
    
    val feature4_index = new StringIndexer()  .setInputCol("feature4")  .setOutputCol("feature4_index")
    val feature6_index = new StringIndexer()  .setInputCol("feature6")  .setOutputCol("feature6_index")
    val feature11_index = new StringIndexer()  .setInputCol("feature11")  .setOutputCol("feature11_index")
    val feature8_index = new StringIndexer()  .setInputCol("feature8")  .setOutputCol("feature8_index")
    val feature13_index = new StringIndexer()  .setInputCol("feature13")  .setOutputCol("feature13_index")
    val feature2_index = new StringIndexer()  .setInputCol("feature2")  .setOutputCol("feature2_index")
    val feature5_index = new StringIndexer()  .setInputCol("feature5")  .setOutputCol("feature5_index")
    val feature7_index = new StringIndexer()  .setInputCol("feature7")  .setOutputCol("feature7_index")
    val vectorizer_L1 =  new VectorAssembler()  .setInputCols(Array("feature3",  "feature2_index", "feature6_index", "feature4_index", "feature8_index", "feature7_index", "feature5_index", "feature10", "feature9", "feature12", "feature11_index", "feature13_index", "feature14", "feature15", "feature18", "feature17", "feature16")).setOutputCol("features_L1")
    val feature_pipeline_L1 = new Pipeline()  .setStages(Array( feature4_index, feature6_index, feature11_index,feature8_index, feature13_index,  feature2_index, feature5_index, feature7_index,vectorizer_L1))
    val testPredict= feature_pipeline_L1.fit(featureDf).transform(featureDf)
    val getPOne = udf((v: org.apache.spark.mllib.linalg.Vector) => v(1))
    val getid2 = udf((v: Int) => v)
    val L1_output = model_L1.transform(testPredict).select(getid2($"id2") as "id2",getid2($"prediction") as "L1_prediction",getPOne($"probability") as "probability")
    
    L1_output.repartition(1).write.format("com.databricks.spark.csv").option("header", "true").mode("overwrite").save("/home/L1_output")
    
      }
    };
    

    让我们从根本错误的事情开始:

    • 您使用的功能机制是不正确的
      StringIndexer
      根据数据的分布分配索引,以便同一记录根据其他记录具有不同的编码。您应该使用相同的
      StringIndexerModel
      (-s)进行培训、测试和预测
    • val getid2=udf((v:Int)=>v)
      只是一个昂贵的标识
    持久
    SparkContext

    有多种工具可以保持持久上下文,包括或

    最后,您可以简单地使用Spark流,并在数据到来时进行处理

    洗牌

    您还使用了
    重新分区
    来创建一个单一的CSV文件,因此我假设是一个单一的CSV文件。这个操作非常昂贵,但从定义上讲,它会随机地重新排列RDD中的数据,以创建更多或更少的分区,并在它们之间实现平衡。这总是在网络上洗牌所有数据

    其他注意事项

    如果延迟很重要,并且您只使用一台低性能的机器,那么根本不要使用Spark。这里没有什么好处。在这种情况下,一个好的地方图书馆可以做得更好

    注释

    我们无法访问您的数据或硬件,因此任何要求(如将时间缩短到7秒)都毫无意义