2013-03-24 20 views
3

我想知道如果有寫下面repA的功能惹巴:ZipWith'ing在列

zipOverColumns :: (Source r1 a, Source r2 b) 
       => (a -> b -> c) 
       -> Array r1 DIM1 a 
       -> Array r2 DIM2 b 
       -> Array D DIM2 c 
zipOverColumns f x y = traverse y id lookup where 
    lookup get [email protected](Z :. _ :. r) = f (x ! (Z :. r)) $ get sh 

這裏更快/更好的辦法是一些示例輸出

>>> toList $ zipOverColumns (*) (fromListUnboxed (Z :. 3)  [1,2,3]) 
           (fromListUnboxed (Z :. 2 :. 3) [4,5,6,7,8,9]) 
[4.0,10.0,18.0,7.0,16.0,27.0] 

回答

2

在惹巴3上下文,你的實現是性能最優的。你會發現下面的版本有點更具可讀性:

zipOverColumns2 
    :: (Source r1 a, Source r2 b) 
    => (a -> b -> c) 
    -> Array r1 DIM1 a 
    -> Array r2 DIM2 b 
    -> Array D DIM2 c 
zipOverColumns2 f col arr = zipWith f ccol arr 
    where 
    ccol = fromFunction (extent arr) (\(Z :. _ :. r) -> col ! (Z :. r)) 

zipOverColumns2也比原來快了15%,但它只是一個巧合。

隨着yarr的函數看起來像:

zipOverColumns 
    :: (USource r1 l1 Dim1 a, 
     USource r2 l2 Dim2 b, DefaultIFusion r2 l2 fr fl Dim2, 
     USource fr fl Dim2 c) 
    => (a -> b -> c) 
    -> UArray r1 l1 Dim1 a 
    -> UArray r2 l2 Dim2 b 
    -> UArray fr fl Dim2 c 
zipOverColumns f col arr = imapM mapF arr 
    where 
    mapF (r, _) b = do 
     a <- col `index` r 
     return $ f a b 

這個版本是從30〜85%的速度,這取決於塔的尺寸(我已經測試4,8和1000)。 Gist與它一起玩。

+0

這是我第一次聽說yarr。看起來很有趣。這個設計怎麼樣能讓它在這裏擊敗重做? – 2013-03-25 09:04:21

+0

@Jonathan Fischoff簡要說明:1)'repa'遍歷線性索引並在每次迭代中執行昂貴的積分除法以獲得複合索引(行,列)。 'yarr'分開保存指數。 2)循環展開。閱讀[blogpost](http://habrahabr.ru/post/170571/)瞭解更多信息(俄文版,在Chrome中翻譯此頁)。 – leventov 2013-03-25 10:33:54

+0

然而,Repa 4將會進行流融合並循環展開,因此它將與Yarr完成此任務。 – leventov 2013-03-25 10:36:23