Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 平行哈斯克尔。限制生产者的税率_Haskell_Parallel Processing_Monads - Fatal编程技术网

Haskell 平行哈斯克尔。限制生产者的税率

Haskell 平行哈斯克尔。限制生产者的税率,haskell,parallel-processing,monads,Haskell,Parallel Processing,Monads,在Haskell的并行和并发编程中,Simon Marlow根据以下数据以及一些生产者和消费者提供了一个: data IList a = Nil | Cons a (IVar (IList a)) type Stream a = IVar (IList a) streamFromList :: NFData a => [a] -> Par (Stream a) streamFromList xs = do var <- new fork $

在Haskell的并行和并发编程中,Simon Marlow根据以下数据以及一些生产者和消费者提供了一个:

data IList a
  = Nil
  | Cons a (IVar (IList a))

type Stream a = IVar (IList a)

streamFromList :: NFData a => [a] -> Par (Stream a)
streamFromList xs = do
      var <- new
      fork $ loop xs var
      return var
    where
      loop [] var = put var Nil
      loop (x:xs) var = do
        tail <- new
        put var (Cons x tail)
        loop xs tail
然而,他并没有完成这种方法:

我将把这个想法的其余部分作为练习留给你自己去尝试。查看是否可以修改
streamFromList
streamFold
streamMap
以合并
Fork
构造函数。区块大小和分叉距离应该是生产者的参数(
streamFromList
streamMap

同样的问题,但没有人回答


那么如何限制生产者的比率呢?

重要的部分在于
循环功能:

  loop [] var = put var Nil
  loop (x:xs) var = do
    tail <- new
    put var (Cons x tail)
    loop xs tail
在每次迭代中,分叉距离都会减小。当叉距离为零时,我们需要做什么?我们提供了一个
Fork op t
,其中
op
继续生成列表:

  loop 0 c (x:xs) var = do
    tail <- new
    let op = loop c xs tail
    put var (Fork op (Cons x tail))
现在,为了使用它,我们需要更改
streamFold
中的
大小写

streamFold :: (a -> b -> a) -> a -> Stream b -> Par a
streamFold fn acc instrm = acc `seq` do
  ilst <- get instrm
  case ilst of
    Cons h t          -> streamFold fn (fn acc h) t
    Fork p (Cons h t) -> -- see below
    _                 -> return acc

streamMap
类似。只有在这种情况下,才能在循环中再次使用其他参数,如
streamFromList

我认为以下是一个有效的实现

{-# LANGUAGE BangPatterns #-}

import Control.Monad.Par (IVar, Par, fork, get, new, put, put_, runPar)
import Control.DeepSeq   (NFData, rnf)

data IList a
  = Nil
  | Cons a (IVar (IList a))
  | Fork (Par ()) (IVar (IList a))

instance NFData a => NFData (IList a) where
  rnf Nil = ()
  rnf (Cons a b) = rnf a `seq` rnf b
  rnf (Fork a b) = rnf (runPar a) `seq` rnf b

type Stream a = IVar (IList a)

main :: IO ()
main = print $ sum (pipeline [1 .. 10000])

pipeline :: [Int] -> [Int]
pipeline list = runPar $ do
  strm <- streamFromList list 100 200
  xs   <- streamFold (\x y -> (y : x)) [] strm
  return (reverse xs)

streamFromList :: NFData a => [a] -> Int -> Int -> Par (Stream a)
streamFromList xs k n = do
    var <- new
    fork $ loop xs var k
    return var
  where
    loop [] var _ = put var Nil
    loop xs var 0 = do
      var' <- new
      put_ var (Fork (loop xs var' n) var')
    loop (x:xs) var i = do
      tail <- new
      put var (Cons x tail)
      loop xs tail (i - 1)

streamFold :: (a -> b -> a) -> a -> Stream b -> Par a
streamFold fn !acc strm = do
  ilst <- get strm
  case ilst of
    Nil      -> return acc
    Cons h t -> streamFold fn (fn acc h) t
    Fork p s -> fork p >> streamFold fn acc s
{-#语言模式}
进口控制,MaNAD.PAR(IVAR,PAR,FACK,GET,NEW,PUT,PUTIG,RUNPAR)
导入控制.DeepSeq(NFData,rnf)
数据列表a
=零
|Cons a(IVar(ILST a))
|Fork(Par())(IVar(IList a))
实例NFData=>NFData(IList a),其中
rnf Nil=()
rnf(Cons a b)=rnf a`seq`rnf b
rnf(Fork a b)=rnf(runPar a)`seq`rnf b
类型流a=IVar(IList a)
main::IO()
main=打印$sum(管道[1..10000])
管道::[Int]->[Int]
管道列表=runPar$do
STRM[A] -INT> INT> PAR(流A)
streamFromList xs k n=do

Value:ValueNoDATA实例定义为<代码> For < /代码>构造函数是:<代码> RNF(OrthyA)= RNF A < /C> >即忽略<代码> PAR(<)/Cord>字段> @ USE5402:<代码> NealPar A= PAR{RunCONT::(A->Trror)> Trace} /Cult>,因此操作是一个简单的函数。因此,受函数的NFData实例(
NFData(a->b)
)的启发,我将使用
rnf(Fork op a)=seq op$rnf a
let op=loop c xs tail
streamFromList :: NFData a => Int -> Int -> [a] -> Par (Stream a)
streamFromList f c xs = do
  var <- new                            
  fork $ loop f c xs var                 
  return var 
streamFold :: (a -> b -> a) -> a -> Stream b -> Par a
streamFold fn acc instrm = acc `seq` do
  ilst <- get instrm
  case ilst of
    Cons h t          -> streamFold fn (fn acc h) t
    Fork p (Cons h t) -> -- see below
    _                 -> return acc
    Fork p (Cons h t) -> fork p >> streamFold fn (fn acc h) t
{-# LANGUAGE BangPatterns #-}

import Control.Monad.Par (IVar, Par, fork, get, new, put, put_, runPar)
import Control.DeepSeq   (NFData, rnf)

data IList a
  = Nil
  | Cons a (IVar (IList a))
  | Fork (Par ()) (IVar (IList a))

instance NFData a => NFData (IList a) where
  rnf Nil = ()
  rnf (Cons a b) = rnf a `seq` rnf b
  rnf (Fork a b) = rnf (runPar a) `seq` rnf b

type Stream a = IVar (IList a)

main :: IO ()
main = print $ sum (pipeline [1 .. 10000])

pipeline :: [Int] -> [Int]
pipeline list = runPar $ do
  strm <- streamFromList list 100 200
  xs   <- streamFold (\x y -> (y : x)) [] strm
  return (reverse xs)

streamFromList :: NFData a => [a] -> Int -> Int -> Par (Stream a)
streamFromList xs k n = do
    var <- new
    fork $ loop xs var k
    return var
  where
    loop [] var _ = put var Nil
    loop xs var 0 = do
      var' <- new
      put_ var (Fork (loop xs var' n) var')
    loop (x:xs) var i = do
      tail <- new
      put var (Cons x tail)
      loop xs tail (i - 1)

streamFold :: (a -> b -> a) -> a -> Stream b -> Par a
streamFold fn !acc strm = do
  ilst <- get strm
  case ilst of
    Nil      -> return acc
    Cons h t -> streamFold fn (fn acc h) t
    Fork p s -> fork p >> streamFold fn acc s