从Apache Spark中的文件联合一系列RDD的内存有效方式

dic*_*e89 6 nlp scala bigdata apache-spark word2vec

我目前正在尝试在UMBC Webbase语料库上训练一组Word2Vec向量(大约30GB的文本在400个文件中).

即使在100 GB以上的机器上,我也经常遇到内存不足的情况.我在应用程序本身运行Spark.我尝试稍微调整一下,但我无法对超过10 GB的文本数据执行此操作.我实现的明显瓶颈是先前计算的RDD的并集,即内存不足异常的来源.

也许您有经验可以提出比这更有效的内存实现:

 object SparkJobs {
  val conf = new SparkConf()
    .setAppName("TestApp")
    .setMaster("local[*]")
    .set("spark.executor.memory", "100g")
    .set("spark.rdd.compress", "true")

  val sc = new SparkContext(conf)


  def trainBasedOnWebBaseFiles(path: String): Unit = {
    val folder: File = new File(path)

    val files: ParSeq[File] = folder.listFiles(new TxtFileFilter).toIndexedSeq.par


    var i = 0;
    val props = new Properties();
    props.setProperty("annotators", "tokenize, ssplit");
    props.setProperty("nthreads","2")
    val pipeline = new StanfordCoreNLP(props);

    //preprocess files parallel
    val training_data_raw: ParSeq[RDD[Seq[String]]] = files.map(file => {
      //preprocess line of file
      println(file.getName() +"-" + file.getTotalSpace())
      val rdd_lines: Iterator[Option[Seq[String]]] = for (line <- Source.fromFile(file,"utf-8").getLines) yield {
          //performs some preprocessing like tokenization, stop word filtering etc.
          processWebBaseLine(pipeline, line)    
      }
      val filtered_rdd_lines = rdd_lines.filter(line => line.isDefined).map(line => line.get).toList
      println(s"File $i done")
      i = i + 1
      sc.parallelize(filtered_rdd_lines).persist(StorageLevel.MEMORY_ONLY_SER)

    })

    val rdd_file =  sc.union(training_data_raw.seq)

    val starttime = System.currentTimeMillis()
    println("Start Training")
    val word2vec = new Word2Vec()

    word2vec.setVectorSize(100)
    val model: Word2VecModel = word2vec.fit(rdd_file)

    println("Training time: " + (System.currentTimeMillis() - starttime))
    ModelUtil.storeWord2VecModel(model, Config.WORD2VEC_MODEL_PATH)  
  }}
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*bos 1

正如 Sarvesh 在评论中指出的那样,对于一台机器来说,这可能是太多的数据。使用更多机器。我们通常需要 20-30 GB 内存才能处理 1 GB 的文件。通过这个(非常粗略的)估计,您需要 600-800 GB 的内存来处理 30 GB 的输入。(您可以通过加载部分数据来获得更准确的估计。)

作为更一般的评论,我建议您避免使用rdd.unionsc.parallelizesc.textFile与通配符一起使用可将所有文件加载到单个 RDD 中。