首页 > 解决方案 > 向并行代码添加进度条 (Haskell)

问题描述

在 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 如何评估表达式的理解引起了我的困惑,因此任何关于这方面的指示也会有所帮助。

标签: haskell

解决方案


不幸的是,我相信 GHC 目前没有公开任何功能来观察(IO显然)并行计算的评估进度。您将需要以forkIO和朋友的形式(或像async包一样包装它们的库)来使用并发。


推荐阅读