跟踪"地图"的进度

Sho*_*hoe 11 parallel-processing haskell

我有一个map操作(实际上是使用parMapfrom 并行运行Control.Parallel.Strategies)需要很长时间.鉴于我知道该函数的应用次数(n在此上下文中),我如何能够轻松地每隔一段时间显示n已评估了多少应用程序?

最明显的解决办法是让地图中的mapM一些putStr映射函数里面,但是这将:

  • 采取不必要的效率
  • 不是偶尔对每个应用程序中的状态进行采样
  • 基本上在并行化的上下文中删除了关于确定性算法的所有好处

那么,有没有办法跟踪这些我遗漏的信息,避免这些问题?

j.p*_*.p. 2

在生产中,您可能不应该使用跟踪,并且被迫处理需要 IO 的复杂性,但对于测试,您可以修改 parMap 的定义以采用另一个参数来告诉何时发出计数:

import Control.Monad (sequence)
import Control.Parallel.Strategies (Strategy, using, rseq, rparWith, parMap)
import Debug.Trace (traceShow)
import System.IO (hFlush, hSetBuffering, BufferMode(NoBuffering), stdout)

evalList' :: Integer -> Strategy a -> Strategy [a]
evalList' t s as = sequence $ foldr f [] $ zip as [1..]
  where f (a, n) ss | n `mod` t == 0 = s (traceShow n a):ss
                    | otherwise      = s a:ss

parList' :: Integer -> Strategy a -> Strategy [a]
parList' t s = evalList' t (rparWith s)

parMap' :: Integer -> Strategy b -> (a -> b) -> [a] -> [b]
parMap' t s f xs = map f xs `using` parList' t s

-- some work to do
fib :: Integer -> Integer
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib(n-2)

main = do hSetBuffering stdout NoBuffering
          print $ sum (parMap' 1000 rseq (fib.(+20).(`mod` 5)) ([1..10000]::[Integer]))
Run Code Online (Sandbox Code Playgroud)

如果每个列表元素给出的工作包变得很小,您可以相应地调整 parListChunk。