Man, is it slick! Using the factors code from the last post, it was so easy to write a program that parallelized the factorizations of different numbers. My code took two command line arguments: the first number to factor, and the number of consecutive numbers to factor. The base version of the code was
getFactorStr :: Integer -> StringThe parallel version isn't a lot more complicated:
getFactorStr x = concat $ intersperse "," $
map show $ factors x
getFactorStrRange :: Integer -> Integer -> [String]
getFactorStrRange x y = map getFactorStr [x..y]
main = do
args <- getArgs let start = read $ args !! 0
let end = (start + (read $ args !! 1))
mapM putStrLn $ getFactorStrRange start end
getFactorStr' :: Integer -> Par StringNow I'm sure it took me longer than it would have taken a more experienced Haskell programmer, but whenever I got into trouble I just had to look at the types of things to find my way out. Like the baseball coach says, you've just got to keep your eye on the type.
getFactorStr' x = do
calc <- spawn $ return $ concat $ intersperse "," $
map show $ factors x
v <- get calc
return v
getFactorStrRange' :: Integer -> Integer -> Par [String]
getFactorStrRange' x y = parMapM getFactorStr' [x..y]
main = do
args <- getArgs let start = read $ args !! 0
let end = (start + (read $ args !! 1))
mapM putStrLn $ runPar $ getFactorStrRange' start end
And how did the timing work out? On my quad-core Athlon II machine, the parallel version ran about 3.2x as fast as the sequential version (15.1 seconds vs 48.6 seconds). This was a crude timing test -- I made no effort to control for what other processes on the system were doing.