我已经开发了一个累积和函数,如下面在Haskell库Repa中定义的那样.但是,在将此函数与转置操作组合时,我遇到了一个问题.以下所有3项操作都在一秒钟内完成:
cumsum $ cumsum $ cumsum x
transpose $ transpose $ transpose x
transpose $ cumsum x
Run Code Online (Sandbox Code Playgroud)
但是,如果我写:
cumsum $ transpose x
Run Code Online (Sandbox Code Playgroud)
性能骇人听闻.虽然单独的每个操作在1920x1080图像上都不到一秒钟,但当它们合并时,它们现在需要30秒以上......
关于可能导致这种情况的任何想法?我的直觉告诉我它与延迟阵列有关,而不是在正确的时间强迫等等......但是我还没有足够的经验去追踪它.
{-# LANGUAGE TypeOperators, FlexibleContexts, TypeFamilies #-}
import Data.Array.Repa as Repa
{-# INLINE indexSlice #-}
indexSlice :: (Shape sh, Elt a) => Int -> Array (sh :. Int) a -> (sh :. Int) -> a
indexSlice from arr (z :. ix) = arr `unsafeIndex` (z :. (ix + from))
{-# INLINE sliceRange #-}
sliceRange :: (Slice sh, …Run Code Online (Sandbox Code Playgroud) 我试图使用Repa实现累积和函数以计算积分图像.我目前的实现如下所示:
cumsum :: (Elt a, Num a) => Array DIM2 a -> Array DIM2 a
cumsum array = traverse array id cumsum'
where
elementSlice inner outer = slice array (inner :. (0 :: Int))
cumsum' f (inner :. outer) = Repa.sumAll $ elementSlice inner outer
Run Code Online (Sandbox Code Playgroud)
问题出在elementSlice函数中.在matlab中或说numpy,这可以指定为array [inner,0:outer].所以我正在寻找的是:
slice array (inner :. (Range 0 outer))
Run Code Online (Sandbox Code Playgroud)
但是,似乎不允许在当前的Repa范围内指定切片.我考虑过在Haskell中使用高效并行模板卷积中讨论的分区,但如果每次迭代都改变它,这似乎是一个相当重要的方法.我还考虑过屏蔽切片(乘以二进制矢量) - 但这似乎再次对大型矩阵执行得很差,因为我会为矩阵中的每个点分配一个掩码矢量...
我的问题 - 有没有人知道是否有计划增加支持切片范围到维修?或者是否有一种高效的方式我可以解决这个问题,也许采用不同的方法?