代码之家  ›  专栏  ›  技术社区  ›  danbroooks

cabal似乎无法构建并行运行的可执行文件

  •  1
  • danbroooks  · 技术社区  · 6 年前

    我目前正在阅读《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 ,这是从书中删掉的,我敢肯定这对我的问题无关紧要。

    所以当我试着和卡巴尔一起运行这个代码时会发生以下情况:

    λ 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 也许?

    1 回复  |  直到 6 年前
        1
  •  4
  •   soupi    6 年前

    也许试着跑:

    time cabal new-run sudoku -- par 16000 +RTS -N2
    

    这个 -- 通常说“这些标志属于执行的程序”。