簡體   English   中英

Haskell並行化和線程中的嚴格評估。

[英]Haskell parallelisation and strict evaluation in thread..?

我試圖從給定的數字列表中找到素數。 到目前為止,我有一段有效的代碼,但是如果我取消注釋某些行並注釋其他行,則看不到速度的任何差異。 我幾乎可以肯定,我必須在單獨的線程中強制執行評估,因為我認為我是在啟動線程的,但是由於懶惰而未在此處評估代碼。 但是我找不到強制這種評估的方法。 我根據此處的示例進行工作。 因此,我將函數parMapstrMap並行映射和嚴格的[parallel]映射。 parMap ,有2行已注釋,因此,如果您取消注釋它們,並注釋掉當前未注釋的其他4行,那么您不會注意到速度上的任何差異,盡管它應該是不平行且較慢的。 我現在也忽略了main函數中的程序args。

所以基本上我的問題是-是否有可能實現針對parMap給出的列表中的每個數字,產生一個新線程,從而使所有工作都更快?

代碼如下:

module W7T5
(
  main
) where

import Control.Concurrent
import Control.Parallel (par, pseq)
import System.Environment

main = do
  args' <- getArgs
  let
--    args = map (\x -> read x :: Int) args'
    args = [2000000..2000200]
    tfPrime = parMap isPrime' args
--    tfPrime = strMap isPrime' args
    argsNtf = zip args tfPrime
    primes' = filter (\(num, tfPrime) -> tfPrime) argsNtf
    primes = map fst primes'
  putStrLn ("Init list: " ++ show args)
  putStrLn ("Primes   : " ++ show primes)

-- Map in parallel
parMap :: NFData a => (a -> b) -> [a] -> [b]
parMap _ [] =
  []
--parMap f (x:xs) = -- sadly without any parallelisation it's not slower
--  (f x) :parMap f xs
parMap f (x:xs) =
  par r (r:parMap f xs)
  where
    r = f x

-- Map in parallel strictly
strMap :: (a -> b) -> [a] -> [b]
strMap f xs =
  forceList xs `seq` map f xs

forceList :: [a] -> ()
forceList (x:xs) =
  xs `pseq` forceList xs
forceList _ =
  ()

isPrime' :: Int -> Bool
isPrime' 0 = True
isPrime' 1 = True
isPrime' 2 = True
isPrime' num =
  all (/=0) [mod num x | x <- [2..(num-1)]]

您可以使用

runhaskell W7T5.hs 1 2 3 4

為了提高速度(這是並行性的要點),應編譯Haskell程序(使用ghc ),而不是對其進行解釋(使用runghc )。 我完全不知道如何實際使用runghc進行多線程。

ghc W7T5 -threaded -with-rts -N2
./W7T5

parMap實現是不正確的:計算(r : parMap f xs)立即返回並且僅尾部(r : parMap f xs) ,尾部只會在需要時才觸發(但到那時將為時已晚)。 下方的一個會在連接前先激發頭部和尾部,因此在調用者看到構造函數時,列表的其余部分將在后台進行評估。

parMap :: (a -> b) -> [a] -> [b]
parMap f [] = []
parMap f (x : xs) = rs `par` r `par` (r : rs)
  where
    r = f x
    rs = parMap f xs

編譯程序時,您可能看不到與解釋器相同的緩沖行為,因為可執行文件默認情況下使用行緩沖。 可以使用System.IO.hSetBuffering關閉緩沖

import System.IO

main = do
  hSetBuffering stdout NoBuffering
  ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM