6

我对为什么 REPA 函数computeP将其结果打包在一个单子中感到困惑。它具有以下类型签名。

computeP :: (Load r1 sh e, Target r2 e, Source r2 e, Monad m) =>
            Array r1 sh e -> m (Array r2 sh e)

本教程中它说

这样做的原因是monad 给出了明确定义的序列概念,因此 computeP 强制在 monad 计算的特定点完成并行评估。

同样,堆栈溢出的这个答案指出

Repa 中的并行计算必须是 monadic 的原因部分与惰性有关,但主要与 Repa 无法处理嵌套并行性有关。Monad 的顺序属性在很大程度上解决了它[.]

问题

  • 拥有这种“顺序属性”究竟意味着什么?
  • monad 如何执行此操作?
  • 例如computeP:没有使用哪个monad的限制,所以我可以使用identity monad。那么使用下面的函数来解包 monad 是否可以,或者这会因为它缺少这个顺序属性而产生意想不到的结果?如果可以的话,是否还需要使用 monad?

    import Data.Functor.Identity
    import Data.Array.Repa.Eval
    import Data.Array.Repa
    
    myComputeP :: (Load r1 sh e, Target r2 e, Source r2 e) => Array r1 sh e -> Array r2 sh e
    myComputeP = runIdentity . computeP
    

任何帮助都会很棒。

4

1 回答 1

2

这个单子约束是一种启发式技巧。它帮助有纪律的用户避免嵌套并行,但对恶意或无知的用户无能为力。

嵌套并行是这样一种情况,即在并行计算某个数组时,您最终不得不并行计算另一个数组。Repa 不支持它(原因并不重要),因此它试图避免它。

的类型computeP有助于确保并行计算彼此按顺序完成,但它远非无懈可击;它只是一个“尽力而为”的抽象。

monad 如何执行此操作?

实际上,computeP只希望与绑定(>>=)在其第一个参数中严格的 monad 一起使用,因此在 中u >>= k,该函数仅在评估k后才会应用。u那么如果你使用computeP这样的单子,

do w <- computeP v
   k w

保证w在传递给 之前对向量进行评估k,这可以安全地执行其他computeP操作。

  • 严格单子的示例:IO, strict State, Maybe, [].
  • 惰性单子的示例:Identity,惰性StateReader。(惰性单子可以变得严格,但反过来不行。特别是,如果你只想做 Repa 计算,你可以定义一个严格的恒等单子。)

为了防止嵌套并行, 的类型computeP故意使在可能并行完成的操作中使用起来很麻烦,例如map :: (a -> b) -> Array _ _ a -> Array _ _ band fromFunction :: sh -> (sh -> a) -> Array _ _ a,它采用非单子函数。仍然可以明确地 unwrap computeP,例如,runIdentity正如您注意到的那样:如果您愿意,您可以在脚上开枪,但是您需要为枪上膛,将其指向下方并扣动扳机。


希望这能回答 Repa 发生的事情。以下是回答另一个问题的理论题外话:

拥有这种“顺序属性”究竟意味着什么?

这些引文很随意。在我看来,“顺序性”和“单子”之间的关系是双重的。

首先,对于 Haskell 中的许多 monad, 的定义(>>=)自然地决定了评估的顺序,通常是因为它立即与第一个参数进行模式匹配。如前所述,这就是 Repa 依赖于强制computeP计算按顺序发生的原因(这就是为什么如果你将它专门化它会中断Identity;它不是一个严格的 monad)。从总体上看,这是惰性求值的一个相当小的细节,而不是一般的单子。

其次,纯函数式编程的一个核心思想是一流的计算,具有明确的效果和组合定义。在这种情况下,效果是向量的并行评估,我们关心的组合是顺序组合。Monad 为顺序组合提供了一个通用模型或接口。这也是 monad 有助于解决 Repa 中避免嵌套并行问题的另一部分原因。

重点不是 monad 具有固有的顺序方面,而是顺序组合本质上是 monadic:如果您尝试列出您期望从任何值得称为“顺序组合”的任何东西中获得的一般属性,您可能会结束加上一起称为“monad”的属性;这是 Moggi 的开创性论文“计算和单子的概念”的要点之一。

“单子”不是一个神奇的概念,而是非常笼统的,所以很多东西恰好是单子。毕竟,主要要求是有一个关联操作;这是关于顺序组合的一个非常合理的假设。(如果,当您听到“关联性”时,您想到的是“monoid”或“category”,请注意所有这些概念都统一在“monoid objects”的保护伞下,因此就“associativity”而言,它们是所有相同的想法,只是在不同的类别。)

于 2020-01-05T15:18:23.633 回答