这里有一个基本的 monad 问题,与 Repa 无关,还有几个 Repa 特定的问题。
我正在使用 Repa3 开发一个库。我无法获得高效的并行代码。如果我让我的函数返回延迟的数组,我会得到非常慢的代码,可以很好地扩展到 8 个内核。这段代码每个 GHC 分析器占用超过 20GB 的内存,运行速度比基本的 Haskell 未装箱向量慢几个数量级。
或者,如果我让所有函数都返回未装箱清单数组(仍然尝试在函数中使用融合,例如当我执行“映射”时),我会得到更快的代码(仍然比使用 Haskell 未装箱向量慢)根本无法扩展,事实上随着内核的增多,速度会变得稍微慢一些。
基于 Repa-Algorithms 中的 FFT 示例代码,似乎正确的方法是始终返回清单数组。有没有我应该返回延迟数组的情况?
FFT 代码还大量使用了“现在”功能。但是,当我尝试在代码中使用它时出现类型错误:
type Arr t r = Array t DIM1 r
data CycRingRepa m r = CRTBasis (Arr U r)
| PowBasis (Arr U r)
fromArray :: forall m r t. (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r
fromArray =
let mval = reflectNum (Proxy::Proxy m)
in \x ->
let sh:.n = extent x
in assert (mval == 2*n) PowBasis $ now $ computeUnboxedP $ bitrev x
没有“现在”,代码编译得很好。使用“现在”,我收到以下错误:
无法匹配类型
r' with
数组 U (Z :. Int) r' `r' 是一个刚性类型变量,受 fromArray :: (BaseRing mr, Unbox r, Repr tr) => Arr tr -> CycRingRepa mr 的类型签名约束在 C:\Users\crockeea\Documents\Code\LatticeLib\CycRingRepa.hs:50:1 预期类型:CycRingRepa mr 实际类型:CycRingRepa m (Array U DIM1 r)
我不认为 这是我的问题。如果有人可以解释 Monad 在“现在”中的工作方式,那将会很有帮助。根据我的最佳估计,单子似乎正在创建一个“Arr U (Arr U r)”。我期待一个“Arr U r”,它将匹配数据构造函数模式。发生了什么事,我该如何解决?
类型签名是:
computeUnboxedP :: Fill r1 U sh e => Array r1 sh e -> Array U sh e
now :: (Shape sh, Repr r e, Monad m) => Array r sh e -> m (Array r sh e)
更好地了解何时使用“现在”会有所帮助。
其他几个 Repa 问题:我应该显式调用 computeUnboxedP(如 FFT 示例代码中所示),还是应该使用更通用的 computeP(因为 unbox 部分是由我的数据类型推断的)?我应该将延迟数组或清单数组存储在数据类型 CycRingRepa 中吗?最终,我还希望这段代码与 Haskell Integers 一起使用。这是否需要我编写使用 U 数组以外的东西的新代码,或者我是否可以编写多态代码来为 unbox 类型创建 U 数组和为 Integers/boxed 类型创建其他数组?
我意识到这里有很多问题,我感谢任何/所有答案!