haskell - 未装箱向量中没有与 unsafeUpdate_ 进行流融合

标签 haskell vector stream fusion

处理 vector 时是否可以保持流融合如果unsafeUpdate_函数用于更新 vector 的一些元素?在我所做的测试中,答案似乎是否定的。对于下面的代码,临时向量在 upd 中生成。功能,如核心中所确认:

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函数用于 sum - 如下所示,它生成新的 bytearray :

$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 的核心中有一个很好的、紧密的循环。函数,但就在该循环之前,调用了 $wupd函数,因此,临时生成。

有没有办法避免这里示例中的临时生成?我的想法是,更新索引 i 中的向量是解析流的情况,但仅作用于索引 i 中的流(跳过其余部分),并将其中的元素替换为另一个元素。因此,在任意位置更新向量不应破坏流融合,对吧?

最佳答案

我不能 100% 确定,因为 vector它一直都是乌龟(你永远不会真正到达实际的实现,总是有另一个间接的),但据我了解,更新变体通过克隆强制一个新的临时:

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

modifyWithStream调用clone(和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)

而且我认为 vector 无法再次摆脱该 unsafeCopy

关于haskell - 未装箱向量中没有与 unsafeUpdate_ 进行流融合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16995850/

相关文章:

haskell - cabal 沙箱安装仍然失败,错误为 "packages are likely to be broken by the reinstalls"

haskell - 构建相同的镜头

c++ - 堆损坏 - 为什么?

c - 在 numpy vector 上使用标量 C 函数

python - 如何将文本文件读入文本框?

windows - cabal 安装 pcap Windows 64 位

haskell - 为什么 Haskell/unpack 会弄乱我的字节?

c++ - 具有任意索引范围的类 STL vector

javascript - 在更新时显示日志文件的内容

java - 服务器和客户端之间的通信标准