Haskell 跟踪“地图”的进度`

Haskell 跟踪“地图”的进度`,haskell,parallel-processing,Haskell,Parallel Processing,我有一个map操作(实际上是使用Control.parallel.Strategies中的parMap并行运行的),这需要相当长的时间。既然我知道函数被应用了多少次(n,在这种情况下),我怎么能每隔一段时间轻松地显示有多少个n应用程序被评估过 显而易见的解决方案是在映射函数中使用一些putStr使映射成为mapM,但这将: 取得不必要的效率 不是每隔一段时间采样一次,而是在每个应用程序中采样一次 基本上去掉了并行环境中确定性算法的所有优点 那么,有没有一种方法可以跟踪我所缺少的信息,从而避免

我有一个
map
操作(实际上是使用
Control.parallel.Strategies
中的
parMap
并行运行的),这需要相当长的时间。既然我知道函数被应用了多少次(
n
,在这种情况下),我怎么能每隔一段时间轻松地显示有多少个
n
应用程序被评估过

显而易见的解决方案是在映射函数中使用一些
putStr
使映射成为
mapM
,但这将:

  • 取得不必要的效率
  • 不是每隔一段时间采样一次,而是在每个应用程序中采样一次
  • 基本上去掉了并行环境中确定性算法的所有优点

那么,有没有一种方法可以跟踪我所缺少的信息,从而避免这些问题?

人们可以尝试使用

seconds::Int
秒=1000000
进度::[a]->IO()
进度[]=返回()
进展l@(x:xs)=
执行r进程l--重试
只需y->执行putStrLn“一个完成!”
进展xs

小心,因为我担心
超时
会中止计算。如果有另一个线程计算
x
,这应该没问题,但如果这是唯一一个这样做的线程,那么如果5秒不够,它可能会导致死锁。

在生产中,您可能不应该使用跟踪,并且被迫处理需要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]))

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

除了在罗马尼亚语中显然是“锦标赛”的意思外,“campionate”是什么意思?您可能想看看
monad par
包。它看起来不太适合你所看到的地方,但是<代码>控制。可以想象的是,你可以勾入那种粘液,让ThreadScope运行,但我怀疑这会给你想要的东西。另一种选择可能是使用一些可怕和不安全的东西,如
trace
unsafePerformIO
,让线程报告完成情况。我认为关键的问题是“某个线程是否完成了?”在纯上下文中不是一个有意义的问题。您应该添加
parMap
的类型,或者提及它是否来自
Control.Parallel.Strategies
@dfeuer-Woops。我想我的意思是“样品”。@杰弗里:不,你完全明白。每隔一段时间显示一次状态必然导致
IO
。这正是德弗尔提到的。“我的地图完成了多少?”这个问题不能用纯代码来回答。
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]))