gpt4 book ai didi

haskell - Repa 2 和 3 API 之间的主要区别是什么?

转载 作者:行者123 更新时间:2023-12-04 01:52:16 24 4
gpt4 key购买 nike

更具体地说,我有以下看起来无害的小 Repa 3 程序:

{-# LANGUAGE QuasiQuotes #-}

import Prelude hiding (map, zipWith)
import System.Environment (getArgs)
import Data.Word (Word8)
import Data.Array.Repa
import Data.Array.Repa.IO.DevIL
import Data.Array.Repa.Stencil
import Data.Array.Repa.Stencil.Dim2

main = do
[s] <- getArgs
img <- runIL $ readImage s

let out = output x where RGB x = img
runIL . writeImage "out.bmp" . Grey =<< computeP out

output img = map cast . blur . blur $ blur grey
where
grey = traverse img to2D luminance
cast n = floor n :: Word8
to2D (Z:.i:.j:._) = Z:.i:.j

---------------------------------------------------------------

luminance f (Z:.i:.j) = 0.21*r + 0.71*g + 0.07*b :: Float
where
(r,g,b) = rgb (fromIntegral . f) i j

blur = map (/ 9) . convolve kernel
where
kernel = [stencil2| 1 1 1
1 1 1
1 1 1 |]

convolve = mapStencil2 BoundClamp

rgb f i j = (r,g,b)
where
r = f $ Z:.i:.j:.0
g = f $ Z:.i:.j:.1
b = f $ Z:.i:.j:.2

在我的 2Ghz core 2 duo 笔记本电脑上处理 640x420 图像需要这么多时间:
real    2m32.572s
user 4m57.324s
sys 0m1.870s

我知道肯定有什么问题,因为我在使用 Repa 2 的更复杂的算法上获得了更好的性能。在该 API 下,我发现的重大改进来自于在每次数组转换之前添加对“强制”的调用(我理解表示每次调用映射、卷积、遍历等)。我不能完全弄清楚在 Repa 3 中要做的类似事情 - 事实上,我认为新的表现类型参数应该确保在何时需要强制数组时没有歧义?新的一元接口(interface)如何适应这个方案?我已阅读 Don S 的精彩教程,但 Repa 2 和 3 API 之间存在一些关键差距,在线 AFAIK 很少讨论。

更简单地说,是否有一种影响最小的方法来解决上述程序的效率问题?

最佳答案

新的表示类型参数不会在需要时自动强制(这可能是一个很难做到的问题) - 您仍然必须手动强制。在 Repa 3 中,这是通过 computeP 函数完成的:

computeP
:: (Monad m, Repr r2 e, Fill r1 r2 sh e)
=> Array r1 sh e -> m (Array r2 sh e)

我个人真的不明白为什么它是 monadic,因为你也可以使用 Monad Identity:
import Control.Monad.Identity (runIdentity)
force
:: (Repr r2 e, Fill r1 r2 sh e)
=> Array r1 sh e -> Array r2 sh e
force = runIdentity . computeP

所以,现在你的 output函数可以用适当的强制重写:
output img = map cast . f . blur . f . blur . f . blur . f $ grey
where ...

带有缩写 f使用辅助函数 u帮助类型推断:
u :: Array U sh e -> Array U sh e
u = id
f = u . force

通过这些更改,加速非常显着——这是意料之中的,因为没有中间强制,每个输出像素最终评估的结果远远超出了必要的范围(中间值不共享)。

您的原始代码:
real    0m25.339s
user 1m35.354s
sys 0m1.760s

强制:
real    0m0.130s
user 0m0.320s
sys 0m0.028s

使用 600x400 png 进行测试,输出文件是相同的。

关于haskell - Repa 2 和 3 API 之间的主要区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10747079/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com