11

Để cụ thể hơn, tôi có ít chương trình Repa 3 vô hại-looking sau:Sự khác biệt chính giữa API Repa 2 và 3 là gì?

{-# 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 

nào mất nhiều thời gian này để xử lý một hình ảnh 640x420 trên 2Ghz core 2 duo máy tính xách tay của tôi:

real 2m32.572s 
user 4m57.324s 
sys  0m1.870s 

Tôi biết điều gì đó phải sai, vì tôi đã có hiệu suất tốt hơn nhiều trên các thuật toán phức tạp hơn bằng cách sử dụng Repa 2. Theo API đó, cải tiến lớn mà tôi tìm thấy đến từ việc thêm một lời gọi vào 'force' trước mỗi biến đổi mảng (mà tôi hiểu nghĩa là mọi cuộc gọi đến bản đồ, convolve, đi qua vv). Tôi không thể làm ra điều tương tự để làm trong Repa 3 - trên thực tế tôi nghĩ rằng các thông số kiểu biểu hiện mới được cho là để đảm bảo không có sự mơ hồ về khi một mảng cần phải bị ép buộc? Và giao diện monadic mới phù hợp với chương trình này như thế nào? Tôi đã đọc hướng dẫn hay của Don S, nhưng có một số khoảng trống chính giữa API Repa 2 và 3 mà ít được thảo luận trực tuyến về AFAIK.

Đơn giản hơn, có cách nào có tác động tối thiểu để khắc phục hiệu quả của chương trình trên không?

Trả lời

10

Các tham số kiểu đại diện mới không tự động bắt buộc khi cần thiết (có thể là một vấn đề khó để thực hiện tốt) - bạn vẫn phải ép buộc theo cách thủ công. Trong Repa 3 này được thực hiện với các chức năng computeP:

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

Cá nhân tôi thực sự không hiểu tại sao nó monadic, vì bạn có thể chỉ cần cũng sử dụng Monad nhận dạng:

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 

Vì vậy, bây giờ bạn output chức năng có thể được viết lại với buộc thích hợp:

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

với viết tắt f sử dụng một hàm helper u để hỗ trợ suy luận kiểu:

u :: Array U sh e -> Array U sh e 
u = id 
f = u . force 

Với những thay đổi này, tăng tốc khá ấn tượng - đó là để được mong đợi, như không có trung gian buộc mỗi điểm ảnh đầu ra kết thúc đánh giá nhiều hơn là cần thiết (các giá trị trung gian không được chia sẻ) .

mã ban đầu của bạn:

real 0m25.339s 
user 1m35.354s 
sys  0m1.760s 

Với buộc:

real 0m0.130s 
user 0m0.320s 
sys  0m0.028s 

Thử nghiệm với một png 600x400, các tập tin đầu ra là giống hệt nhau.

+0

Đây là một câu trả lời tuyệt vời! Tôi đã hiểu rằng tính toánP là sự thay thế cho 'lực lượng', nhưng đã không nghĩ đến việc sử dụng nó với danh tính đơn sắc. Tôi đánh giá cao sự giúp đỡ của bạn. – sacheie

+1

Tôi tin rằng lý do sử dụng các kiểu trả về đơn thuần là vì ý tưởng buộc một cái gì đó ở khá chặt chẽ với các lực lượng xảy ra liên tục. Có giải thích tốt hơn trong http://www.cse.unsw.edu.au/~chak/papers/LCKP12.html – Axman6

7

computePforce mới.

Trong Repa 3 bạn cần phải sử dụng computeP khắp mọi nơi bạn đã sử dụng force trong Repa 2.

Các Laplace ví dụ từ repa-ví dụ tương tự như những gì bạn đang làm. Bạn cũng nên sử dụng cmap thay vì đồng bằng map trong chức năng blur của mình. Sẽ có một bài báo giải thích lý do tại sao trên trang chủ của tôi vào đầu tuần tới.

+0

Điều tuyệt vời về cộng đồng Haskell - phản hồi từ chính các nhà phát triển thư viện :) Tôi háo hức chờ đợi bài viết của bạn. – sacheie