Adding a Progress Bar to Parallel Code (Haskell)

Viewed 104

In Haskell, I have a list that can be evaluated in parallel. Each individual evaluation doesn't take that long, but there are many of them (1 million, for example). I'm using the following library. The plan is split the list into chunks and run them in parallel. I have something like the following that works:

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

I would like to add a progress bar to this so I can keep track of how much of the list has been done. My instinct was to try something like the following:

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

But force doesn't seem to be able to handle IO. I've tried a couple other things, but whatever I try evaluates the list of IO [Int] in parallel but not the actual contents of the IO. I see that the parallel library has some functions like withStrategyIO, although I'm not sure how to use it or if it's what I'm looking for.

I think my understanding of how Haskell evaluates expressions is causing my confusion, so any pointers on that would be helpful as well.

1 Answers

Unfortunately, I believe GHC currently does not expose any functionality for observing (in IO, obviously) the evaluation progress of parallel computations. You will need to use concurrency in the form of forkIO and friends (or a library that wraps them like the async package) instead.

Related