Как сохранить тип данных 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) пример .
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 cInts, Аn- й точкой является3n,3n+1,3n+2Ints.
Comments