How to store Haskell data type in Unboxed Vector in continuous memory

I would like to keep a nonparametric, decompressed data type like

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

The vector is unboxed. Data.Vector.Unboxed says:

In particular, unpacked vectors of pairs are represented as pairs of unrecognized vectors.

Why? I would prefer my Point3D place one after another in memory to get fast cache-local access when iterating through them sequentially - the equivalent of mystruct[1000] in C.

Using Vector.Unboxed or otherwise, how can I achieve this?


By the way: vector-th-unbox the same thing happens, because with this you just convert your data type to (Unbox a, Unbox b) => Unbox (a, b) instance .

+6
source share
1 answer

I don’t know why the vectors of pairs are stored as pairs of vectors, but you can easily write instances for your data type to store elements in sequence.

 {-# 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 

At this point, the last line will Point3D error because there are no instances for Point3D for vector types. They can be written as follows:

 instance M.MVector MVector Point3D where basicLength (MV_Point3D v) = M.basicLength v `div` 3 basicUnsafeSlice ab (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 abc basicUnsafeWrite (MV_Point3D v) n (Point3D abc) = 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 ab (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 abc 

I think most function definitions are self-evident. The vector of points is stored as the vector Int , and the n th point is 3n , 3n+1 , 3n+2 Int s.

+9
source

All Articles