3

次のrepa関数を書くためのより速い/より良い方法があるかどうか疑問に思っています

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 sh@(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]
4

1 に答える 1

2

Repa 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 をテストしました)。それを使って遊ぶための要点。

于 2013-03-24T10:06:01.190 に答える