Aby być bardziej konkretne, mam następujący niewinnie wyglądające trochę Repa 3 program:Jakie są kluczowe różnice między interfejsami API Repa 2 i 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
Która zajmuje to dużo czasu na przetworzenie do 640x420 obraz na moim 2Ghz Core 2 Duo laptop:
real 2m32.572s
user 4m57.324s
sys 0m1.870s
Wiem, że coś musi być w błędzie, ponieważ uzyskałem znacznie lepszą wydajność w przypadku bardziej złożonych algorytmów korzystających z Repa 2. Pod tym API, znaczna poprawa, którą odkryłem, pochodziła z dodania wywołania "force" przed każdą transformacją tablicy (którą rozumieć każde wezwanie do mapowania, konwergowania, trawersowania itp.). Nie bardzo rozumiem analogiczną rzecz do zrobienia w Repa 3 - w rzeczywistości myślałem, że parametry nowego typu manifestacji mają zapewnić, że nie ma dwuznaczności, kiedy tablica musi zostać zmuszona? A jak nowy monadyczny interfejs pasuje do tego schematu? Przeczytałem ładny tutorial autorstwa Dona S, ale są pewne kluczowe luki między interfejsami API Repa 2 i 3, które są mało omawiane w Internecie AFAIK.
Po prostu, czy istnieje minimalnie skuteczny sposób, aby poprawić wydajność powyższego programu?
To jest świetna odpowiedź! Zrozumiałem, że computeP zastępuje "siłę", ale nie myślał, że użyje jej z monadą tożsamości. Doceniam twoją pomoc. – sacheie
Uważam, że powodem stosowania monadycznych typów powrotu jest to, że idea wymuszania czegoś jest ściśle związana z siłami, które następują kolejno. Lepsze wyjaśnienie znajdziesz w http://www.cse.unsw.edu.au/~chak/papers/LCKP12.html – Axman6