我不确定这是否 100% 适用于accelerate
or repa
,但这是我过去为 Vector 处理的一种方法:
-- | A hopefully-efficient sink that incrementally grows a vector from the input stream
sinkVector :: (PrimMonad m, GV.Vector v a) => Int -> ConduitM a o m (Int, v a)
sinkVector by = do
v <- lift $ GMV.new by
go 0 v
where
-- i is the index of the next element to be written by go
-- also exactly the number of elements in v so far
go i v = do
res <- await
case res of
Nothing -> do
v' <- lift $ GV.freeze $ GMV.slice 0 i v
return $! (i, v')
Just x -> do
v' <- case GMV.length v == i of
True -> lift $ GMV.grow v by
False -> return v
lift $ GMV.write v' i x
go (i+1) v'
它基本上分配by
空槽并继续填充它们。一旦达到上限,它就会再次增长底层向量。我没有对任何东西进行基准测试,但它在实践中似乎表现不错。我很想知道这里是否会有其他更有效的答案。
希望这在某种程度上有所帮助。我确实看到有一个fromVector
功能repa
,也许这是您结合此方法的金票。