Как сохранить тип данных Haskell в распакованном векторе в непрерывной памяти



Я хотел бы сохранить непараметрический, распакованный тип данных, такой как



data Point3D = Point3D {-# UNPACK #-} !Int {-# UNPACK #-} !Int {-# UNPACK #-} !Int


В распакованном векторе. данные.Вектор.Unbox говорит:



В частности, распакованные векторы пар представляются в виде пар распакованных векторов.


Почему это? Я бы предпочел, чтобы мои Point3D выкладывались один за другим в памяти, чтобы получить быстрый кэш-локальный доступ при последовательном переборе их-эквивалент mystruct[1000] В C.



Используя Vector.Unboxed или иначе как я могу этого достичь?





Кстати: с vector-th-unbox происходит то же самое, так как при этом вы просто преобразуете свой тип данных в (Unbox a, Unbox b) => Unbox (a, b) пример .

460   1  

1 ответ:

Я не знаю, почему векторы пар хранятся как пары векторов, но вы можете легко написать экземпляры для вашего типа данных, чтобы хранить элементы последовательно.

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

import qualified Data.Vector.Generic as G 
import qualified Data.Vector.Generic.Mutable as M 
import Control.Monad (liftM, zipWithM_)
import Data.Vector.Unboxed.Base

data Point3D = Point3D {-# UNPACK #-} !Int {-# UNPACK #-} !Int {-# UNPACK #-} !Int

newtype instance MVector s Point3D = MV_Point3D (MVector s Int)
newtype instance Vector    Point3D = V_Point3D  (Vector    Int)
instance Unbox Point3D

В этом месте последняя строка вызовет ошибку, так как нет экземпляров для векторных типов для Point3D. Их можно записать следующим образом:

instance M.MVector MVector Point3D where 
  basicLength (MV_Point3D v) = M.basicLength v `div` 3 
  basicUnsafeSlice a b (MV_Point3D v) = MV_Point3D $ M.basicUnsafeSlice (a*3) (b*3) v 
  basicOverlaps (MV_Point3D v0) (MV_Point3D v1) = M.basicOverlaps v0 v1 
  basicUnsafeNew n = liftM MV_Point3D (M.basicUnsafeNew (3*n))
  basicUnsafeRead (MV_Point3D v) n = do 
    [a,b,c] <- mapM (M.basicUnsafeRead v) [3*n,3*n+1,3*n+2]
    return $ Point3D a b c 
  basicUnsafeWrite (MV_Point3D v) n (Point3D a b c) = zipWithM_ (M.basicUnsafeWrite v) [3*n,3*n+1,3*n+2] [a,b,c]

instance G.Vector Vector Point3D where 
  basicUnsafeFreeze (MV_Point3D v) = liftM V_Point3D (G.basicUnsafeFreeze v)
  basicUnsafeThaw (V_Point3D v) = liftM MV_Point3D (G.basicUnsafeThaw v)
  basicLength (V_Point3D v) = G.basicLength v `div` 3
  basicUnsafeSlice a b (V_Point3D v) = V_Point3D $ G.basicUnsafeSlice (a*3) (b*3) v 
  basicUnsafeIndexM (V_Point3D v) n = do 
    [a,b,c] <- mapM (G.basicUnsafeIndexM v) [3*n,3*n+1,3*n+2]
    return $ Point3D a b c 
Я думаю, что большинство определений функций не требуют объяснений. Вектор точек хранится в виде вектора Ints, А n - й точкой является 3n,3n+1,3n+2 Ints.

Comments

    Ничего не найдено.