11

更具體,我有以下看似平淡無奇的小惹巴3的程序:Repa 2和3 API之間的主要區別是什麼?

{-# 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下,我發現的重大改進來自每次數組轉換之前對'force'的調用理解爲意味着每次調用映射,卷積,遍歷等)。我不能完全理解Repa 3中的類似事情 - 事實上,我認爲新的表現類型參數應該確保關於數組何時需要被迫的模糊性。新的monadic接口如何適應這種方案?我已閱讀Don S的精彩教程,但Repa 2和3 API之間的一些關鍵差距很少在線討論AFAIK。

更簡單地說,是否有一個微不足道的方法來解決上述程序的效率?

回答

10

新的表示類型參數在需要時不會自動強制執行(可能很難做到這一點) - 您仍然必須手動強制。

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

我個人真的不明白爲什麼它的單子,因爲你可以一樣好使用Monad的身份:在惹巴3,這是與computeP函數來完成

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 

所以,現在你的使用輔助功能u幫助

output img = map cast . f . blur . f . blur . f . blur . f $ grey 
    where ... 

利用縮寫foutput功能可以通過適當的強制改寫類型推斷:

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測試,輸出文件是相同的。

+0

這是一個很好的答案!我明白,computeP是'force'的替代品,但並沒有想到將它與monad身份一起使用。我感謝您的幫助。 – sacheie

+1

我相信使用monadic返回類型的原因是因爲強迫某事的想法與順序發生的強制緊密相關。 http://www.cse.unsw.edu.au/~chak/papers/LCKP12.html有更好的解釋 – Axman6

7

computeP是新的force

在惹巴3,您需要使用computeP無處不在,你會在惹巴2

已經使用force從repA的-例子的Laplace例子類似於你在做什麼。您還應該在blur函數中使用cmap而不是map。將有一篇論文解釋爲什麼在我的主頁下週初。

+0

Haskell社區的偉大之處 - 來自圖書館開發者自己的反饋:)我熱切期待您的論文。 – sacheie

相關問題