2013-09-05 2 views
0

Следующие работы, но ужасно неэффективны.
Я подозреваю, что это мое использование конкатенации списка, которое является причиной.Неэффективный генератор случайных списков

import Control.Parallel.Strategies (runEval, rpar) 
import Data.Text      (Text) 
import qualified Data.Text.IO as T (writeFile) 
import Text.InterpolatedString.Perl6 (qq) 
-- random data imports 
import Crypto.Random.AESCtr   (makeSystem) 
import System.Random     (split, randomR, randomRs) 


-- |This function picks a random element from a list 
-- choose :: RandomGen g => g  --^random generator 
--      -> [a] --^list to be taken from 
--      -> (a, g) --^random pick 
choose g lst = let ra = randomR (0::Int, length lst -1) g 
       in (lst !! fst ra, snd ra) 

и

-- |This function generates a set of french SSN numbers 
-- http://mon-convertisseur.fr/calculateur-cle-numero-securite-sociale.php 
-- sans check digits 
-- genFrSSN :: RandomGen g => g  --^random generator 
--       -> [Text] --^list of data 
genFrSSN g = [fin] ++ genFrSSN g5 
    where 
    (sex, g1) = choose g [1..2] 
    (yBirth, g2) = choose g1 [70..99] 
    (mBirth, g3) = choose g2 [10..12] 
    (depart, g4) = choose g3 [21..95] 
    commune  = 999 
    (numOrd, g5) = randomR (100::Int, 300) g4 
    -- using interpolatedstring-perl6 
    -- because for some other generator I may have not have only Int data 
    fin   = [qq|$sex$yBirth$mBirth$depart$commune$numOrd|] :: Text 

, который я переписал в

genFrSSN g = runEval $ do 
    a <- rpar [fin] 
    b <- rpar $ genFrSSN (snd sx) 
    return (a ++ b) 
    where 
    sx   = split g 
    (sex, g1) = choose (fst sx) [1..2] 
    (yBirth, g2) = choose g1 [70..99] 
    (mBirth, g3) = choose g2 [10..12] 
    (depart, g4) = choose g3 [21..95] 
    commune  = 999 
    (numOrd, _) = randomR (100::Int, 300) g4 
    fin   = [qq|$sex$yBirth$mBirth$depart$commune$numOrd|] :: Text 

Но вместо того, чтобы быть низко я просто запустить из памяти и процессора злоупотребляют. Генератор должен дать мне бесконечный список, из которого я возьму переменное количество элементов.
Я использую списки из-за [Char], который удобен при наличии нескольких данных ввода

Кулак, как я могу избавиться от (++)? А во-вторых, пожалуйста, критикуйте.

+0

Вы можете опустить '++', построив обратный список, а затем вызовите 'reverse'. Но я не думаю, что это вызывает проблемы с производительностью. –

+0

Если производительность имеет значение, то используйте одну из реализаций MT, а не 'random'. –

+0

Я искал в hoogle, но не нашел пакетов MT. Может быть, mersenne-pure94? – rakwatt

ответ

2

++ не является проблемой. Похоже, вы когда-либо использовали его для добавления списков элементов в любом случае.

Почему не просто randomR (70,99) вместо choose g [70..99]? Это просто бесполезная неэффективность. Вы можете сделать это, когда хотите выбрать из диапазона значений в Enum. Но в общем случае вы можете повысить эффективность choose (когда вам это действительно нужно), заставив его работать над структурой данных с помощью O (1) length и (!!) вместо списков.

Проблема заключается в параллельной оценки. Я недостаточно разбираюсь в этом материале, чтобы помочь вам там, но когда я пытаюсь скомпилировать вашу программу без опции -threaded, она работает быстро и с низкой постоянной памятью. Используя -threaded, я получаю ошибку из памяти. Я не знаю, почему это так, но я не думаю, что вы должны распараллелить этот материал в первую очередь. Задача не является по своей сути параллельной.

+0

Да, у меня была пунктуальная потребность в выборе (не в списке), и я закончил, я не знаю, зачем ее использовать в любом месте. – rakwatt

+0

Perf немного улучшились, но я не до его коллег в perl (я должен был сделать один генератор в perl из-за удобства) – rakwatt

+0

Если вы хотите получить производительность до уровня с Perl, вы должны опубликовать оба источника для сравнения. Это может оправдать новый вопрос. – firefrorefiddle

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