2017-03-09 7 views
0

HashTableパッケージを使用してHaskellにBayes naiveクラシファイアを作成しています。しかし、大きなコーパスを処理するとき、おそらく膨大な数の値の更新が原因で大量のメモリリークが発生します。すでに指定された単語数を読み込むときには約2GBのRAMが必要ですが、単語の出現数をコーパスから計算すると8GBのRAMで十分ではなく、クラッシュします。どうすればそれを防ぐことができますか?コードが言葉をカウントすると、そのようになっていますテキストキー付きハッシュテーブルを使用しているときにメモリリークが発生する

chars :: T.Text 
chars = "qwertyuiopasdfghjklzxcvbnmęóąśłżźćń\t " 

el :: Char -> T.Text -> Bool 
el = T.any . (==) 

preprocess :: T.Text -> [T.Text] 
preprocess !line = T.words . T.map check . T.toLower $ line 
      where check !x = if x `el` chars then x else ' ' 

loop :: Handle -> Corpus -> IO() 
loop hdl dic = 
    hIsEOF hdl >>= \x -> if x 
     then return() 
     else do 
      cl:dat <- preprocess <$> TIO.hGetLine hdl 
      let ins !word = 
         if (T.length word <= 20) && (T.length word >= 4) 
          then (H.lookup dic word >>= 
           \mprob -> case mprob of 
            Just (SexProbs m f) -> do 
            H.delete dic word 
            H.insert dic word $ if cl == "m" then SexProbs (m+1) f else SexProbs m (f+1) 
            Nothing -> H.insert dic word $ if cl == "m" then SexProbs 1 0 else SexProbs 0 1) 
          else return() 
      mapM_ ins dat 
      loop hdl dic 

プロファイリング割り当ての最大の原因は、前処理とループしているが、私はメモリ使用量を削減する方法が分からないことを示唆しています。

+0

は、あなたの輸入を記入してくださいことはできますか?どのHashTableバリアントを使用していますか?テキストが厳密か怠惰ですか? – Chris

+0

また、 'SexProbs'の定義を追加します - フィールドが厳密でない限り、' + 1'はリークを引き起こします。 – Chris

+0

どのようにコンパイルしていますか? – jberryman

答えて

1

原因は、SexProbsデータ型のようです。それはおそらく、(カウンタのIntを想定)怠惰な分野、すなわちで定義されます。

SexProbs (m+1) nで新たな価値を構築
data SexProbs = SexProbs Int Int 

は追加の評価が、ヒープメモリにサンクを置かないであろう。これらは蓄積し、スペースリークを引き起こす。 seq

let m' = m+1 in m' `seq` SexProbs m' n 

や厳格なフィールドを使用するように型定義を変更するとカウンターの評価を強制する、これを回避する

data SexProbs = SexProbs !Int !Int 
関連する問題