2015-02-28 3 views
2

Я пытаюсь обрабатывать данные Point Cloud с помощью Haskell, и, похоже, он использует много памяти. Код, который я использую, приведен ниже, он в основном анализирует данные в формате, с которым я могу работать. Набор данных имеет 440 МБ с 10 М строк. Когда я запускаю его с runhaskell, он использует все баран в течение короткого времени (~ 3-4gb), а затем сработает. Если я скомпилирую его с -O2 и запустил его, он перейдет на 100% процессор и займет много времени (~ 3 минуты). Я должен упомянуть, что я использую i7 cpu с 4 ГБ оперативной памяти и SSD, поэтому должно быть много ресурсов. Как я могу улучшить производительность?Haskell скорость/использование памяти

{-# LANGUAGE OverloadedStrings #-} 
import Prelude hiding (lines, readFile) 
import Data.Text.Lazy (Text, splitOn, unpack, lines) 
import Data.Text.Lazy.IO (readFile) 
import Data.Maybe (fromJust) 
import Text.Read (readMaybe) 

filename :: FilePath 
filename = "sample.txt" 

readTextMaybe = readMaybe . unpack 

data Classification = Classification 
    { id :: Int, description :: Text 
    } deriving (Show) 

data Point = Point 
    { x :: Int, y :: Int, z :: Int, classification :: Classification 
    } deriving (Show) 

type PointCloud = [Point] 

maybeReadPoint :: Text -> Maybe Point 
maybeReadPoint text = parse $ splitOn "," text 
    where toMaybePoint :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Text -> Maybe Point 
      toMaybePoint (Just x) (Just y) (Just z) (Just cid) cdesc = Just (Point x y z (Classification cid cdesc)) 
      toMaybePoint _ _ _ _ _         = Nothing 
      parse :: [Text] -> Maybe Point 
      parse [x, y, z, cid, cdesc] = toMaybePoint (readTextMaybe x) (readTextMaybe y) (readTextMaybe z) (readTextMaybe cid) cdesc 
      parse _      = Nothing 

readPointCloud :: Text -> PointCloud 
readPointCloud = map (fromJust . maybeReadPoint) . lines 

main = (readFile filename) >>= (putStrLn . show . sum . map x . readPointCloud) 
+0

Не используйте List, конвертируйте этот список в вектор. Кроме того, использование тестовой памяти с помощью двоичных файлов, о которых вы знаете, у вас есть оптимизация. – bitemyapp

+0

@bitemyapp, как я уже говорил выше, я пробовал использовать «-O2», и, хотя он не заполняет память, он по-прежнему очень медленный. –

+0

Преобразование списка в вектор. – bitemyapp

ответ

3

Причина этого использует всю память, когда компилируется без оптимизации, скорее всего, потому что sum определяется с помощью foldl. Без анализа строгости, который приходит с оптимизацией, это сильно взорвется. Вы можете попробовать использовать эту функцию вместо:

sum' :: Num n => [n] -> n 
sum' = foldl' (+) 0 

Причиной этого является медленным при компиляции с оптимизацией кажется, вероятно, связано с тем, как вы синтаксический анализ входного сигнала. Концы будут выделены для каждого символа при чтении на входе, а также при разрыве входа в строки и, возможно, еще раз при разбиении на запятую. Использование соответствующей библиотеки синтаксического анализа (любой из них) почти наверняка поможет; использование одного из потоковых, например pipes, или conduit может быть или не быть лучшим (я не уверен).

Другая проблема, не связанная с производительностью: fromJust - довольно плохая форма в целом, и это действительно плохая идея при работе с пользовательским вводом. Вместо этого вы должны сделать mapM над списком в монаде Maybe, который будет производить для вас Maybe [Point].

Смежные вопросы