首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Repa2和Repa3API之间的主要区别是什么?

Repa2和Repa3API之间的主要区别是什么?
EN

Stack Overflow用户
提问于 2012-05-25 08:34:59
回答 2查看 794关注 0票数 11

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

代码语言:javascript
复制
{-# 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

在我的2 2Ghz酷睿2 duo笔记本电脑上处理640x420图像需要这么多时间:

代码语言:javascript
复制
real    2m32.572s
user    4m57.324s
sys     0m1.870s

我知道有些地方肯定出了问题,因为我使用REPA2在更复杂的算法上获得了更好的性能。在这个API下,我发现的最大改进来自于在每个数组转换之前添加了一个'force‘调用(我理解这意味着每个对map、卷积、遍历等的调用)。我不太清楚在REPA3中要做的类似事情--事实上,我认为新的显示类型参数应该确保在何时需要强制数组时不会有歧义?新的一元接口如何适应这种方案?我已经读过Don S的很好的教程,但是在Repa2和3API之间有一些关键的差距,很少有人在线讨论AFAIK。

更简单地说,有没有一种影响最小的方法来修复上面程序的效率?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-27 19:22:45

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

代码语言:javascript
复制
computeP
  :: (Monad m, Repr r2 e, Fill r1 r2 sh e)
  => Array r1 sh e -> m (Array r2 sh e)

我个人真的不明白为什么它是一元的,因为你也可以使用Monad Identity:

代码语言:javascript
复制
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函数:

代码语言:javascript
复制
output img = map cast . f . blur . f . blur . f . blur . f $ grey
  where ...

使用辅助函数u的缩写f来辅助类型推断:

代码语言:javascript
复制
u :: Array U sh e -> Array U sh e
u = id
f = u . force

有了这些变化,加速是相当惊人的-这是意料之中的,因为没有中间强制每个输出像素最终计算的结果比必要的多得多(中间值不共享)。

你的原始代码:

代码语言:javascript
复制
real    0m25.339s
user    1m35.354s
sys     0m1.760s

使用强制:

代码语言:javascript
复制
real    0m0.130s
user    0m0.320s
sys     0m0.028s

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

票数 10
EN

Stack Overflow用户

发布于 2012-05-27 19:15:14

computeP是新的force

在REPA3中,你需要在任何你在REPA2中使用force的地方使用computeP

repa-examples中的Laplace示例与您正在做的类似。您还应该在blur函数中使用cmap而不是普通的map。下周初我的主页上会有一篇论文解释为什么。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10747079

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档