使用Haskell的Repa实现2D Torus数组

3

我刚开始研究Repa,并想知道如何实现环绕式的torus 2D数组读/写。 我以前使用ST monad和mutable vectors实现过这个功能,但似乎Repa不支持。 有几种方法可能可行:

  • 我可以'遍历'数组,并在每个元素处自己执行索引包装。 对于简单的stencil,到处应用wrapping逻辑的成本非常严重,所以我需要避免这种方法。

  • Data.Array.Repa.Stencil不支持我需要的边界条件,但看起来Data.Array.Repa.Algorithms.Convolve支持。文档提到了严重的性能损失

  • 我了解到,可以使用slices遍历数组的子集。 因此,我可以定义一个内部(1,1) - (w-2,h-2),两个水平和两个垂直板块表示边界,然后使用两个不同的函数/ stencils遍历它们,从而得到单个结果数组?是否有任何样本代码或进一步的文档说明?

  • Repa似乎还有'partitions'的概念,它们可用于实现边界条件吗?

哪种方法最快? 是否有我遗漏的选项?

谢谢!

1个回答

3
最有效的方法是使用分区数组表示法(第四个选项),但它不太方便,因为你需要手动处理5个区域
Yarr中,你可以编写一个实用程序。
dim2WrapAround :: USource r l Dim2 a => UArray r l Dim2 a -> Dim2 -> Dim2 -> IO a
{-# INLINE dim2WrapAround #-}
dim2WrapAround arr (sizeX, sizeY) (posX, posY) =
    index arr (wrap sizeX posX, wrap sizeY posY)
  where wrap size pos = (pos + size) `mod` size

-- I'm afraid to write the signature...
{-# INLINE convolveOnThorus #-}
convolveOnThorus = convolveLinearDim2WithStaticStencil dim2WrapAround

使用方法:

myConvolution :: UArray F L Dim2 Float -> UArray CV CVL Dim2 Float
myConvolution = convolveOnThorus [dim2St| some
                                           coeffs
                                               here |]

convolveLinearDim2WithStaticStencil 函数只在边界处的 dim2WrapAround 环绕时,才会使用。还是每个元素都用呢?在我看来,这基本上与 Data.Array.Repa.Algorithms.Convolve 中的 ConvolveP 函数相同。(聪明的环绕逻辑,顺便说一句。我会用两个分支或模数来实现它,不错!) - NBFGRTW
@AN1仅在边界处。不,名称convolveDim2WithStaticStencil指定它确实是静态的,甚至比Repa 3中的静态模板卷积更快。 - leventov
@AN1 还有,我的“聪明”包装方法是错误的...决定还是用模数更好。请查看答案的编辑。 - leventov
好的,我明白了,并且它支持任意边界条件,不像 Repa stencil 强制我使用动态边界条件。又是一个值得检查的库!就 Repa 看看,你知道有没有关于 Slices/Partitions 的好样例代码等内容?官方文档有点稀少,而 Parallel Haskell 书籍和 Haskell.org 教程似乎也没有解释清楚它们;-( - NBFGRTW
@AN1 切片肯定不适合这项任务。 探索模板的实现:http://hackage.haskell.org/packages/archive/repa/3.2.3.3/doc/html/src/Data-Array-Repa-Stencil-Dim2.html#mapStencil2 - leventov
哦,刚看到“--将数组分成内部和边界区域”的部分,太棒了,谢谢! - NBFGRTW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接