在Haskell中,我有一个可以并行计算的列表。每个单独的评估不会花那么长时间,但有很多(例如100万(。我正在使用以下库。计划是将列表拆分成块,并并行运行。我有一些类似以下的东西可以工作:
import Control.Parallel.Strategies
import Control.DeepSeq
-- Imagine this being slightly more expensive
kindaExpensiveComputation :: Int -> [Int]
kindaExpensiveComputation n = replicate n 42
main :: IO ()
main = do
let n = 1000000
let args = replicate n 20
let chunkSize = n `div` 10
let result = force $ withStrategy (parListChunk chunkSize rseq) . map kindaExpensiveComputation $ args
-- do stuff with result here
-- end program
我想添加一个进度条,这样我就可以跟踪列表中完成了多少工作。我的本能是尝试以下内容:
import Control.Parallel.Strategies
import Control.DeepSeq
import System.ProgressBar
-- Imagine this being slightly more expensive
kindaExpensiveComputation :: ProgressBar s -> Int -> IO [Int]
kindaExpensiveComputation pb n = do
let res = replicate n 42
incProgress pb 1
return res
main :: IO ()
main = do
let n = 1000000
let args = replicate n 20
let chunkSize = n `div` 10
pb <- newProgressBar defStyle 10 (Progress 0 n ())
let result = force $ withStrategy (parListChunk chunkSize rseq) . map (kindaExpensiveComputation pb) $ args
-- do stuff with result here
-- end program
但是force
似乎不能处理IO
。我尝试了其他一些方法,但无论我尝试什么,都会并行评估IO [Int]
的列表,而不是IO
的实际内容。我看到并行库有一些类似withStrategyIO
的函数,尽管我不确定如何使用它,也不确定它是否是我想要的。
我认为我对Haskell如何计算表达式的理解导致了我的困惑,所以任何关于这方面的指针都会很有帮助。
不幸的是,我认为GHC目前没有公开任何用于观察(显然在IO
中(并行计算的评估进度的功能。您将需要以forkIO
和friends(或者像async
包一样封装它们的库(的形式使用并发。