簡體   English   中英

關於運行Hadoop作業的java.lang.OutOfMemoryError

[英]java.lang.OutOfMemoryError on running Hadoop job

我有一個輸入文件(大小約為31GB),其中包含有關某些產品的消費者評論,我試圖將其引入並找到相應的引理計數。 該方法有點類似於Hadoop提供的WordCount示例。 我總共有4個類來執行處理:StanfordLemmatizer [包含來自斯坦福的coreNLP軟件包v3.3.0的lemmatizing的好東西],WordCount [驅動程序],WordCountMapper [mapper]和WordCountReducer [reducer]。

我已經在原始數據集的子集(以MB為單位)上測試了程序,並且運行正常。 不幸的是,當我在大小為~31GB的完整數據集上運行作業時,作業失敗了。 我檢查了syslog的工作,它包含了這個:

java.lang.OutOfMemoryError:edu.stanford.nlp.sequences.ExactBestSequenceFinder.bestSequence(ExactBestSequenceFinder.java:109)中的Java堆空間[...]

有關如何處理這個的任何建議?

注意:我正在使用預先配置了hadoop-0.18.0的Yahoo的VM。 我也嘗試過在這個線程中提到的分配更多堆的解決方案: Hadoop中的內存錯誤

WordCountMapper代碼:

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reporter;

public class WordCountMapper extends MapReduceBase
    implements Mapper<LongWritable, Text, Text, IntWritable> {

  private final IntWritable one = new IntWritable(1);
  private final Text word = new Text();
  private final StanfordLemmatizer slem = new StanfordLemmatizer();

  public void map(LongWritable key, Text value,
      OutputCollector output, Reporter reporter) throws IOException {

    String line = value.toString();

    if(line.matches("^review/(summary|text).*"))    //if the current line represents a summary/text of a review, process it! 
    {
        for(String lemma: slem.lemmatize(line.replaceAll("^review/(summary|text):.", "").toLowerCase()))
        {
            word.set(lemma);
            output.collect(word, one);
        }
    }
  }
}

您需要使正在處理的各個單元的大小(即map-reduce中的每個Map作業)合理。 第一個單位是您為StanfordCoreNLP的annotate()調用提供的文檔大小。 您在此處提供的整個文本將被標記化並在內存中處理。 在標記化和處理過的形式中,它比磁盤上的大小大一個數量級。 因此,文檔大小需要合理。 例如,您可以一次傳入一個消費者評論(而不是31GB的文本文件!)

其次,降低一級,POS標記器(在詞形還原之前)是一次注釋一個句子,它使用大型臨時動態編程數據結構來標記句子,這可能比句子大3個數量級。 。 因此,單個句子的長度也需要合理。 如果有很長的文本或垃圾不分成句子,那么你可能也會遇到這個問題。 解決這個問題的一個簡單方法是使用pos.maxlen屬性來避免POS標記超長句子。

ps當然,如果你只需要使用lemmatizer,你就不應該運行像你不使用的解析器,dcoref這樣的注釋器。

如果您的StanfordLemmatizer不是mapreduce作業的一部分,那么配置hadoop堆空間可能對您沒有幫助。 你能提供這份工作的代碼嗎? 所以,我認為限制你的是一般的Java堆空間。

在考慮配置之前先檢查一下:

我看了一下edu.stanford.nlp.sequences.ExactBestSequenceFinder的代碼(你也應該在這里試試)

我不知道你使用的是哪個版本的stanford.nlp,我不熟悉它,但它似乎根據你輸入的“SequenceModel”做了一些操作。 它是這樣開始的:

private int[] bestSequenceNew(SequenceModel ts) {
    // Set up tag options
    int length = ts.length();
    int leftWindow = ts.leftWindow();
    int rightWindow = ts.rightWindow();
    int padLength = length + leftWindow + rightWindow;
    int[][] tags = new int[padLength][];  //operations based on the length of ts
    int[] tagNum = new int[padLength];   //this is the guilty line 109 according to grepcode

所以ts.length()的輸出非常大(或者這個數組沒有更多的Java堆空間)。 你能把它縮小嗎?

編輯

很明顯是String

 line.replaceAll("^review/(summary|text):.", "").toLowerCase()

對於Java堆而言太過分了。 你能檢查一下這是不是你想要的那個? 你能打印它的長度嗎? 也許您應該考慮重新組織31GB數據集,以便它比您現在的工作線路(如果可能的話)更小更小。 可能是因為錯誤而且問題的原因是一條線太大了。

如果無法完成此操作,請打印異常的完整堆棧跟蹤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM