Without Control.Parallel, it uses about 25% of the CPU, namely one core out of four. With the suggestions in RWH it runs faster but still uses only 35% of the CPU max.
So I set about creating a MWE in order to experiment and reach out for help. For some reason, my stripped down program isn't working with parallelism at all!
There's no effect from the R.W.H. ideas. Can I get some suggestions as to why?
-- Run backtracking search for a list of doubles, optimizing a
-- fitness function on the list, called 'evalFunc'. At each step, use 'stepFunc'
-- to generate a list of possible next Doubles that can be added to the list.
-- We are done when the list has 'finalSize' elements.
search1_par :: Int ->
([Double] -> Double) -> ([Double] -> [Double]) -> [Double] -> (Double,[Double])
search1_par finalSize evalFunc stepFunc listIn
| length listIn == finalSize = (evalFunc listIn,listIn)
| otherwise =
let steps = stepFunc listIn
(steps1,steps2) = divideListInTwo steps
f s = search1_par finalSize evalFunc stepFunc $ s:listIn
results1 = map f steps1
results2 = map f steps2
results = force results1 `par` (force results2 `pseq` (results1++results2))
in L.maximumBy (compare `on` fst) results
force :: [a] -> ()
force xs = go xs `pseq` ()
where go (_:xs) = go xs
go [] = 1
divideListInTwo :: [a] -> ([a],[a])
divideListInTwo [] = ([],[])
divideListInTwo xs = (take l xs,drop l xs) where l = length xs `div` 2
---------------------------------------------
-- some sample evaluation (fitness) functions and step generation functions.
eval1 :: [Double] -> Double
eval1 xs = v1 - v2 + v3
where
v1 = sum $ zipWith (*) (cycle [1]) xs
v2 = sum . map (*2) $ zipWith (*) (cycle [1,0]) xs
v3 = sum . map (*3) $ zipWith (*) (cycle [1,0,0]) xs
step1 :: [Double] -> [Double]
step1 xs | l == 0 = take 8 $ xs
| l == 1 = take 8 $ map (/2) xs
| l == 2 = take 8 $ map (*3) xs
where
l = length xs `mod` 3
--------------------------------------------------------------------------------
-- main
main = do
t1 <- getCPUTime
let f :: Double -> String
f x = printf "%5.1f" x
(_,result) = search1_par 13 eval1 step1 [1,2,3]
putStrLn $ concatMap f result
t2 <- getCPUTime
putStrLn $ printf "CPU time: %.3f" ((fromIntegral $ t2-t1) / 1000000000000 :: Double)