2013-06-08 15 views
5

vectorvector işlevi, vector öğesinin bazı öğelerini güncellemek için kullanılırsa, akım kaynaşmasını sürdürmek mümkün mü? Cevap, yaptığım testte hayır gibi görünüyor. çekirdekte teyit aşağıdaki kod için geçici vektör, upd fonksiyon oluşturulur: çekirdeğindeKutulanmamış vektörde unsafeUpdate_ ile akış füzyonu yok

module Main where 
import Data.Vector.Unboxed as U 

upd :: Vector Int -> Vector Int 
upd v = U.unsafeUpdate_ v (U.fromList [0]) (U.fromList [2]) 

sum :: Vector Int -> Int 
sum = U.sum . upd 

main = print $ Main.sum $ U.fromList [1..3] 

, $wupd işlevi sum kullanılır - aşağıda görüldüğü gibi, yeni bytearray oluşturur:

$wupd :: Vector Int -> Vector Int 
$wupd = 
    \ (w :: Vector Int) -> 
    case w `cast` ... of _ { Vector ipv ipv1 ipv2 -> 
    case main11 `cast` ... of _ { Vector ipv3 ipv4 ipv5 -> 
    case main7 `cast` ... of _ { Vector ipv6 ipv7 ipv8 -> 
    runSTRep 
     (\ (@ s) (s :: State# s) -> 
     case >=# ipv1 0 of _ { 
      False -> case main6 ipv1 of wild { }; 
      True -> 
      case newByteArray# (*# ipv1 8) (s `cast` ...) 
      of _ { (# ipv9, ipv10 #) -> 
      case (copyByteArray# ipv2 (*# ipv 8) ipv10 0 (*# ipv1 8) ipv9) 
        `cast` ... 

sum işlevinde çekirdek için güzel, sıkı bir döngü var, ancak bu döngüden hemen önce, $wupd işlevine bir çağrı var, ve böylece, geçici bir nesil.

Örnekte geçici üretimden kaçınmanın bir yolu var mı? Bunu düşünürken, bir vektörü dizin içinde güncellemek, bir akışı ayrıştırmaktır, ancak sadece indeks i'de (geri kalanını atlamak) akımın üzerine etki etmek ve öğeyi başka bir elemanla değiştirmek. Bu nedenle, rastgele bir konumda bir vektörün güncellenmesi, akış kaynaşmasını kesmemeli, değil mi?

+0

: http: //hackage.haskell 'yarr' füzyon ve yerinde değiştirme ile birlikte unrolling destekler .org/paketleri/arşiv/yarr/1.3.1/doc/html/Data-Yarr-Repr-Foreign.html # t: F – leventov

+0

@leventov, çok güzel! Bu kütüphanenin yazarı olduğunuza göre, yukarıdaki vektör örneği için yerinde eriyen güncelleme işlevinin nasıl yazılacağını paylaşır mısınız? Elbette, yarr için yaptıkların burada geçerli olmalı, değil mi? – Sal

+0

büyük, 'yarr-1' dezavantajı. '' IO ile sıkıca bağlanmıştır. Yerinde düzenleme sadece 'yapmak {... yazma arr 0 2; ...} '. – leventov

cevap

5

% 100 emin olamadım çünkü vector ile kaplumbağalar tamamen kapandı (gerçek uygulamaya hiç erişmediniz, her zaman başka bir dolaylılık var), ama anladığım kadarıyla, update varyantları zorla yeni klonlama yoluyla geçici: Ben vector kurtulmak dair bir şekilde görmek

unsafeUpdate_ :: (Vector v a, Vector v Int) => v a -> v Int -> v a -> v a 
{-# INLINE unsafeUpdate_ #-} 
unsafeUpdate_ v is w 
    = unsafeUpdate_stream v (Stream.zipWith (,) (stream is) (stream w)) 

unsafeUpdate_stream :: Vector v a => v a -> Stream (Int,a) -> v a 
{-# INLINE unsafeUpdate_stream #-} 
unsafeUpdate_stream = modifyWithStream M.unsafeUpdate 

ve modifyWithStream aramalar clone (ve new),

modifyWithStream :: Vector v a 
       => (forall s. Mutable v s a -> Stream b -> ST s()) 
       -> v a -> Stream b -> v a 
{-# INLINE modifyWithStream #-} 
modifyWithStream p v s = new (New.modifyWithStream p (clone v) s) 

new :: Vector v a => New v a -> v a 
{-# INLINE_STREAM new #-} 
new m = m `seq` runST (unsafeFreeze =<< New.run m) 

-- | Convert a vector to an initialiser which, when run, produces a copy of 
-- the vector. 
clone :: Vector v a => v a -> New v a 
{-# INLINE_STREAM clone #-} 
clone v = v `seq` New.create (
    do 
    mv <- M.new (length v) 
    unsafeCopy mv v 
    return mv) 

ve Bu unsafeCopy tekrar.

+0

bu [vektör geri dönüşüm kağıdına] göre (http://www.cse.unsw.edu.au/~rl/publications/recycling.pdf), klon/yeni bir araya gelmeme rağmen birlikte kaynaşması bekleniyor benim deneylerim. – Sal

1

Bir veya çok az öğe değiştirmeniz gerekiyorsa, repa ve yarr kitaplıklarında güzel çözümler vardır. Onlar füzyonu korurlar (Ben repa hakkında emin değilim) ve Haskell-idiomatic.

Repa, fromFunction kullanılarak:

upd arr = fromFunction (extent arr) ix 
    where ix (Z .: 0) = 2 
     ix i = index arr i 

Yarr, Delayed kullanılarak: yana

upd arr = Delayed (extent arr) (touchArray arr) (force arr) ix 
    where ix 0 = return 2 
     ix i = index arr i