具体的には、次のような無害に見える小さなRepa3プログラムがあります。
{-# 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コア2デュオラップトップで640x420の画像を処理するには、これだけの時間がかかります。
real 2m32.572s
user 4m57.324s
sys 0m1.870s
Repa 2を使用して、はるかに複雑なアルゴリズムでパフォーマンスが大幅に向上したため、何かがかなり間違っているに違いないことを知っています。そのAPIの下で、すべての配列変換の前に「force」への呼び出しを追加することで、大きな改善が見られました(これは理解しています)マップ、畳み込み、トラバースなどへのすべての呼び出しを意味します)。Repa 3で行う類似のことを完全に理解することはできません。実際、新しいマニフェストタイプのパラメーターは、配列を強制する必要がある場合にあいまいさがないことを保証することになっていると思いましたか?そして、新しいモナディックインターフェイスはこのスキームにどのように適合しますか?Don Sによるすばらしいチュートリアルを読みましたが、Repa2と3のAPIの間には、オンラインAFAIKではほとんど議論されていないいくつかの重要なギャップがあります。
もっと簡単に言えば、上記のプログラムの効率を修正するための最小限の影響を与える方法はありますか?