2016-06-16 3 views
6

Je veux trouver le premier élément correspondant dans une liste infinie dans Haskell.Filtre parallèle liste infinie dans Haskell

Ce code fonctionne:

findPassword passwordHash = (head . filter (checkPassword passwordHash)) allStrings 

checkPassword est très long (parce que c'est un hachage SHA1)

checkPassword hash string = (sha1 string) == hash 

allStrings est juste la liste de toutes les chaînes possibles:

allStrings = [ c : s | s <- "" : allStrings, c <- ['a'..'z'] ++ ['0'..'9'] ] 

Je veux que ce code soit exécuté en parallèle mais si je remplace le filtre par parFilter:

import qualified Control.Parallel.Strategies as S 
parFilter p = S.withStrategy (S.evalBuffer 1000 S.rseq) . filter p 

Cela ne fonctionne pas ... Avez-vous une idée? Ce code utilise également beaucoup de mémoire mais c'est un autre problème. Le script complet est disponible ici https://github.com/ThibaudDauce/habreaker

+0

Comment savez-vous doesn Ne travaillez pas? – Gurkenglas

+0

il court juste pour toujours et mange toute ma RAM et tout mon processeur –

Répondre

5

Je suis sûr que vous voulez utiliser parBuffer au lieu de evalBuffer.

Voir cette réponse SO pour une bonne explication:

How to choose between parList and parBuffer?

Voici un code de démonstration:

import qualified Data.Map.Strict as M 
import Control.Parallel.Strategies 
import System.Environment 
import Debug.Trace 

fib 0 = 0 
fib 1 = 1 
fib n = fib (n-2) + fib (n-1) 

fib' n | trace "calling fib" False = undefined 
fib' n = fib n 

theList = cycle [30,31,32] 

firstN :: Int -> [Int] 
firstN n = take n $ filter even $ map fib' theList 

firstNpar :: Int -> Int -> [Int] 
firstNpar n k = take n $ filter even $ runEval $ parBuffer k rseq $ map fib' theList 

main = do 
    (argn : argk : _) <- getArgs 
    let n = read argn 
    case argk of 
    "" -> print $ firstN n 
    _ -> let k = read argk in 
      print $ firstNpar n k 

Exemple court:

prog 20 2 +RTS -N2   -- I only have two cores 
prog 20 ''     -- run single threaded 
+0

Merci, cela fonctionne (https://github.com/ThibaudDauce/habreaker) mais ce n'est pas plus rapide ... :-(Et je ne vois pas tous mes processeurs de travail ... –

+0

Essayez d'utiliser 'rdeepseq' au lieu de' rseq'. 'Rseq' fonctionne pour mon exemple parce que le résultat de' fib' est juste un nombre, mais vous calculez une paire, donc l'évaluation de WHNF ne calculera pas le hachage. – ErikR