我试图从给定的数字列表中找到素数。
到目前为止,我有一段有用的代码,但如果我取消注释某些行并评论其他一些代码,我认为速度没有任何差别。
我几乎可以肯定我必须在单独的线程中强制进行评估,因为我认为我启动了线程但是由于懒惰而没有在那里评估代码。但我找不到强制评估的方法。我的工作基于例子here。所以我创建了函数parMap
和strMap
,它们是并行映射和严格[并行]映射。在parMap
中有2行注释,所以如果你取消注释它们,并注释掉当前没有注释的其他4行,那么,你不能注意速度的任何差异,尽管它应该是非平行的并且慢一些然后。我现在也忽略了main
函数中的程序参数。
所以基本上我的问题是 - 是否有可能实现,对于给予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
答案 0 :(得分:0)
对于速度(这是并行点),应该编译Haskell程序(使用ghc
)而不是解释(使用runghc
)。我不知道如何实际使用runghc
多线程,如果可能的话。
ghc W7T5 -threaded -with-rts -N2
./W7T5
parMap
实现是不正确的:计算(r : parMap f xs)
立即返回并且只是thunks尾巴,它只会在需要时被引发(但到那时它也会被引发)晚了)。下面的一个会在它们出现之前激发头部和尾部,所以当调用者看到构造函数时,列表的其余部分将在后台进行评估。
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
...