我目前正在阅读《 Haskell中的并行和并发编程》一书,而我正试图让第一个示例在我的机器上运行,这实际上是一些数独解算器算法,该书说明了如何使用haskell在两个核心之间划分求解器的多次迭代。这是代码:
module Main where
import Control.DeepSeq
import Control.Monad
import Control.Parallel.Strategies
import qualified Data.Maybe as M
import Data.Monoid ((<>))
import Sudoku
import System.Environment
data ExecutionMode
= ExecPar
| ExecSeq
main :: IO ()
main = do
execMode <- getExecMode
filepath <- getFilepath
attemptRun execMode filepath
where
attemptRun execMode filepath =
case (execMode, filepath) of
(Just mode, Just file) -> sudoku mode file
(Nothing, _) -> putStrLn "Please provide valid execution mode: 'par' / 'seq'"
_ -> putStrLn "Please choose a file, 1000 / 16000 / 49151"
getExecMode =
(parseExecMode <=< M.listToMaybe) <$> getArgs
getFilepath =
(parseFilepath <=< M.listToMaybe . drop 1) <$> getArgs
parseExecMode "par" = Just ExecPar
parseExecMode "seq" = Just ExecSeq
parseExecMode _ = Nothing
parseFilepath str =
(\n -> "sudoku17." <> n <> ".txt") <$> case str of
"1000" -> Just "1000"
"16000" -> Just "16000"
"49151" -> Just "49151"
_ -> Nothing
sudoku :: ExecutionMode -> String -> IO ()
sudoku execMode filepath = determineMode
where
determineMode =
case execMode of
ExecPar -> runParallel
ExecSeq -> runSequential
runParallel = do
(as, bs) <- (\p -> splitAt (length p `div` 2) p) . lines <$> readFile ("sudoku/data/" <> filepath)
print . length . filter M.isJust . runEval $ do
as' <- rpar (force (map solve as))
bs' <- rpar (force (map solve bs))
_ <- rseq as'
_ <- rseq bs'
return (as' ++ bs')
return ()
runSequential = do
puzzles <- lines <$> readFile ("sudoku/data/" <> filepath)
print . length . filter M.isJust $ solve <$> puzzles
return ()
算法solve
来自Sudoku
,该算法已从书中提炼出来,我很确定这对我的问题无关紧要。
因此,当我尝试使用cabal运行此代码时,会发生以下情况:
λ time cabal new-run sudoku par 16000 +RTS -N2
Up to date
16000
cabal new-run sudoku par 16000 +RTS -N2 17.82s user 0.15s system 100% cpu 17.954 total
然后并行:
λ time cabal new-run sudoku seq 16000 +RTS -N2
Up to date
16000
cabal new-run sudoku seq 16000 +RTS -N2 17.50s user 0.07s system 100% cpu 17.546 total
请注意,时间没有差异。当我使用ghc
进行编译时,会发生以下情况:
λ ghc -O2 sudoku/Main.hs -threaded -v src/Sudoku.hs
λ time sudoku/Main par 16000 +RTS -N2
16000
sudoku/Main par 16000 +RTS -N2 19.59s user 0.28s system 198% cpu 10.034 total
使用seq
标志,它会花费更长的时间,就像您期望的那样:
λ time sudoku/Main seq 16000 +RTS -N2
16000
sudoku/Main seq 16000 +RTS -N2 19.99s user 1.44s system 109% cpu 19.557 total
这是我的.cabal
文件:
build-type: Simple
extra-source-files: ChangeLog.md
cabal-version: >=1.10
library
build-depends: base >=4.8 && <4.9
, array
, time
hs-source-dirs: src
exposed-modules: Sudoku
default-language: Haskell2010
executable sudoku
main-is: Main.hs
ghc-options: -O2 -Wall -Werror -threaded
build-depends: base >=4.8 && <4.9
, deepseq
, parallel
, parallel-and-concurrent-programming-in-haskell
hs-source-dirs: sudoku
default-language: Haskell2010
我在这里错过了什么吗?这是阴谋集团的正确行为吗?还是在ghc-options
和ghc
之间出了问题?
答案 0 :(得分:4)
也许尝试运行:
time cabal new-run sudoku -- par 16000 +RTS -N2
--
通常说“这些标志属于已执行的程序”。