Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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
Arrays Repa阵列上的并行mapM_Arrays_Haskell_Parallel Processing_Repa - Fatal编程技术网

Arrays Repa阵列上的并行mapM

Arrays Repa阵列上的并行mapM,arrays,haskell,parallel-processing,repa,Arrays,Haskell,Parallel Processing,Repa,在我最近的《Gibbs采样》(Gibbs sampling)中,我一直在充分利用它,在我看来,它为随机数生成提供了一个近乎理想的接口。遗憾的是,由于无法在地图中使用一元操作,我一直无法使用Repa 虽然显然一元映射一般不能并行化,但在我看来,RVar可能至少是一个可以安全地并行化效果的单子示例(至少在原则上;我对RVar的内部工作原理不是很熟悉)。也就是说,我想写下面这样的东西 drawClass :: Sample -> RVar Class drawClass = ... drawC

在我最近的《Gibbs采样》(Gibbs sampling)中,我一直在充分利用它,在我看来,它为随机数生成提供了一个近乎理想的接口。遗憾的是,由于无法在地图中使用一元操作,我一直无法使用Repa

虽然显然一元映射一般不能并行化,但在我看来,
RVar
可能至少是一个可以安全地并行化效果的单子示例(至少在原则上;我对
RVar
的内部工作原理不是很熟悉)。也就是说,我想写下面这样的东西

drawClass :: Sample -> RVar Class
drawClass = ...

drawClasses :: Array U DIM1 Sample -> RVar (Array U DIM1 Class)
drawClasses samples = A.mapM drawClass samples
其中
A.mapM
看起来像

mapM :: ParallelMonad m => (a -> m b) -> Array r sh a -> m (Array r sh b)
显然,这将如何工作主要取决于
RVar
及其底层
RandomSource
的实现,但原则上,人们会认为这将涉及为生成的每个线程绘制一个新的随机种子,并照常进行

直觉上,似乎同样的想法也可以推广到其他一些单子

所以,我的问题是:我们能否构造一个单子类
ParallelMonad
,其效果可以安全地并行化(可能至少有
RVar
)呢

它看起来像什么?这个类中还有哪些单子?其他人是否考虑过这在Repa中如何工作的可能性


最后,如果并行一元行为的概念不能被推广,有人认为在
RVar
的特定情况下,有什么好的方法可以使这一点起作用吗?为了并行性而放弃RVar是一个非常困难的权衡。

由于PRNG固有的顺序性,这样做可能不是一个好主意。相反,您可能希望按如下方式转换代码:

  • 声明IO函数(
    main
    ,或您拥有的任何函数)
  • 根据需要阅读尽可能多的随机数字
  • 将(现在为纯)数字传递到repa函数

  • 这个问题已经问了7年了,但似乎仍然没有人想出一个好的解决方案。Repa没有类似于
    mapM
    /
    遍历
    的函数,即使是一个可以在没有并行化的情况下运行的函数。此外,考虑到过去几年取得的进展,这种情况似乎也不太可能发生

    由于Haskell中许多阵列库的陈旧状态,以及我对它们的功能集的总体不满,我对阵列库进行了几年的研究,该阵列库借用了Repa的一些概念,但将其提升到了一个完全不同的层次。介绍够了

    在今天之前,在
    massiv
    中有三个一元地图样函数(不包括同义词样函数:
    imapM
    forM
    等):

    • -任意
      Monad
      中的常用映射。由于明显的原因,不可并行化,而且速度有点慢(与通常的
      mapM
      相比,列表速度慢)
    • -这里我们仅限于
      PrimMonad
      ,它比
      mapM
      快得多,但其原因对于本次讨论并不重要
    • -顾名思义,这一个仅限于
      IO
      (或者更确切地说是
      MonadUnliftIO
      ,但这与此无关)。因为我们在
      IO
      中,所以我们可以自动将数组分割成尽可能多的块,并使用单独的工作线程将
      IO
      操作映射到这些块中的每个元素上。与同样可并行的纯
      fmap
      不同,由于调度的不确定性以及映射操作的副作用,我们必须在
      IO
    所以,当我读到这个问题时,我想这个问题实际上在massiv中得到了解决,但没有那么快。中的随机数生成器和中的其他随机数生成器不能跨多个线程使用同一个生成器。这意味着,我唯一缺少的一块拼图是:“为每个产生的线程绘制一个新的随机种子,并照常进行”。换句话说,我需要两件事:

    • 一个函数,它可以初始化尽可能多的生成器,只要有工作线程
    • 以及一个抽象,它将根据操作运行在哪个线程中无缝地为映射函数提供正确的生成器
    这就是我所做的

    首先,我将给出使用精心编制的and函数的示例,因为它们与问题更相关,然后转到更一般的一元图。以下是他们的类型签名:

    randomArrayWS::
    (可变r ix e,单胞菌属m,单胞菌属m)
    =>WorkerStates g--^使用“initWorkerStates”初始化每线程生成器
    ->Sz ix--^数组的结果大小
    ->(g->me)--^使用每线程生成器生成值。
    ->m(数组r ix e)
    
    initWorkerStates::MonadIO m=>Comp->(WorkerId->ms)->m(WorkerStates)
    
    对于那些不熟悉
    massiv
    的人来说,参数是一种要使用的计算策略,值得注意的构造函数有:

    • Seq
      -按顺序运行计算,不分叉任何线程
    • Par
      -尽可能多地启动线程,并使用这些线程来完成工作
    我将首先以包为例,然后转到
    RVarT

    λ>导入数据.Massiv.Array
    λ> 导入System.Random.MWC(createSystemRandom,uniformR)
    λ> 导入System.Random.MWC.Distributions(标准)
    λ> gens createSystemRandom(随机)
    
    在上面,我们使用系统随机性为每个线程初始化了一个单独的生成器,但是我们也可以通过从参数派生出一个唯一的每个线程种子,它只是worker的
    Int
    索引。现在我们可以用这些发生器来