{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ExplicitNamespaces #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module DataFrame.Internal.RowHash (
computeRowHashesIO,
hashRowRange,
parRowHashThreshold,
) where
import Control.Concurrent (forkIO, getNumCapabilities)
import Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)
import Control.Exception (SomeException, throwIO, try)
import qualified Data.Text as T
import Data.Type.Equality (TestEquality (..), type (:~:) (Refl))
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as VU
import qualified Data.Vector.Unboxed.Mutable as VUM
import System.IO.Unsafe (unsafePerformIO)
import Type.Reflection (typeRep)
import DataFrame.Internal.Column (
Bitmap,
Column (..),
bitmapTestBit,
materializeMerged,
)
import DataFrame.Internal.Hash (
fnvOffset,
mixBytes,
mixDouble,
mixInt,
mixShow,
mixText,
nullSalt,
)
import DataFrame.Internal.PackedText (
PackedTextData (..),
offAt,
packedSlice,
)
import DataFrame.Internal.Types (
SBool (..),
sFloating,
sIntegral,
)
parRowHashThreshold :: Int
parRowHashThreshold :: Int
parRowHashThreshold = Int
200000
capabilities :: Int
capabilities :: Int
capabilities = IO Int -> Int
forall a. IO a -> a
unsafePerformIO IO Int
getNumCapabilities
{-# NOINLINE capabilities #-}
computeRowHashesIO :: Int -> [Column] -> IO (VU.Vector Int)
computeRowHashesIO :: Int -> [Column] -> IO (Vector Int)
computeRowHashesIO Int
n [Column]
selected = do
IOVector Int
mv <- Int -> IO (MVector (PrimState IO) Int)
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
Int -> m (MVector (PrimState m) a)
VUM.unsafeNew (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 Int
n)
let runRange :: Int -> Int -> IO ()
runRange Int
lo Int
hi = IOVector Int -> Int -> Int -> [Column] -> IO ()
hashRowRange IOVector Int
mv Int
lo Int
hi [Column]
selected
if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
parRowHashThreshold Bool -> Bool -> Bool
&& Int
capabilities Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1
then do
let !caps :: Int
caps = Int
capabilities
!per :: Int
per = (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
caps Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
caps
spawn :: Int -> IO (MVar (Either SomeException ()))
spawn Int
w = do
MVar (Either SomeException ())
var <- IO (MVar (Either SomeException ()))
forall a. IO (MVar a)
newEmptyMVar
let !lo :: Int
lo = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
n (Int
w Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
per)
!hi :: Int
hi = Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
n (Int
lo Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
per)
ThreadId
_ <- IO () -> IO ThreadId
forkIO (IO () -> IO (Either SomeException ())
forall e a. Exception e => IO a -> IO (Either e a)
try (Int -> Int -> IO ()
runRange Int
lo Int
hi) IO (Either SomeException ())
-> (Either SomeException () -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MVar (Either SomeException ()) -> Either SomeException () -> IO ()
forall a. MVar a -> a -> IO ()
putMVar MVar (Either SomeException ())
var)
MVar (Either SomeException ())
-> IO (MVar (Either SomeException ()))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure MVar (Either SomeException ())
var
[MVar (Either SomeException ())]
vars <- (Int -> IO (MVar (Either SomeException ())))
-> [Int] -> IO [MVar (Either SomeException ())]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Int -> IO (MVar (Either SomeException ()))
spawn [Int
0 .. Int
caps Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1]
[Either SomeException ()]
rs <- (MVar (Either SomeException ()) -> IO (Either SomeException ()))
-> [MVar (Either SomeException ())] -> IO [Either SomeException ()]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM MVar (Either SomeException ()) -> IO (Either SomeException ())
forall a. MVar a -> IO a
takeMVar [MVar (Either SomeException ())]
vars
(Either SomeException () -> IO ())
-> [Either SomeException ()] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ((SomeException -> IO ())
-> (() -> IO ()) -> Either SomeException () -> IO ()
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall e a. Exception e => e -> IO a
throwIO @SomeException) () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure) [Either SomeException ()]
rs
else Int -> Int -> IO ()
runRange Int
0 Int
n
MVector (PrimState IO) Int -> IO (Vector Int)
forall a (m :: * -> *).
(Unbox a, PrimMonad m) =>
MVector (PrimState m) a -> m (Vector a)
VU.unsafeFreeze (Int -> Int -> IOVector Int -> IOVector Int
forall a s. Unbox a => Int -> Int -> MVector s a -> MVector s a
VUM.slice Int
0 Int
n IOVector Int
mv)
hashRowRange :: VUM.IOVector Int -> Int -> Int -> [Column] -> IO ()
hashRowRange :: IOVector Int -> Int -> Int -> [Column] -> IO ()
hashRowRange IOVector Int
mv Int
lo Int
hi [Column]
cols = do
IOVector Int -> Int -> Int -> IO ()
seedRange IOVector Int
mv Int
lo Int
hi
(Column -> IO ()) -> [Column] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (IOVector Int -> Int -> Int -> Column -> IO ()
mixColumnRange IOVector Int
mv Int
lo Int
hi) [Column]
cols
seedRange :: VUM.IOVector Int -> Int -> Int -> IO ()
seedRange :: IOVector Int -> Int -> Int -> IO ()
seedRange IOVector Int
mv Int
lo Int
hi = Int -> IO ()
go Int
lo
where
go :: Int -> IO ()
go !Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
hi = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
mv Int
i Int
fnvOffset IO () -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> IO ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
mixColumnRange :: VUM.IOVector Int -> Int -> Int -> Column -> IO ()
mixColumnRange :: IOVector Int -> Int -> Int -> Column -> IO ()
mixColumnRange IOVector Int
mv Int
lo Int
hi = \case
c :: Column
c@(MergedColumn Column
_ Column
_) -> IOVector Int -> Int -> Int -> Column -> IO ()
mixColumnRange IOVector Int
mv Int
lo Int
hi (Column -> Column
materializeMerged Column
c)
UnboxedColumn Maybe Bitmap
ubm (Vector a
v :: VU.Vector a) ->
case TypeRep a -> TypeRep Int -> Maybe (a :~: Int)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @Int) of
Just a :~: Int
Refl -> IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> Int -> Int)
-> Vector Int
-> IO ()
forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm Int -> Int -> Int
mixInt Vector a
Vector Int
v
Maybe (a :~: Int)
Nothing ->
case TypeRep a -> TypeRep Double -> Maybe (a :~: Double)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @Double) of
Just a :~: Double
Refl -> IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> Double -> Int)
-> Vector Double
-> IO ()
forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm Int -> Double -> Int
mixDouble Vector a
Vector Double
v
Maybe (a :~: Double)
Nothing ->
case forall a. SBoolI (IntegralTypes a) => SBool (IntegralTypes a)
sIntegral @a of
SBool (IntegralTypes a)
STrue ->
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm (\Int
h a
d -> Int -> Int -> Int
mixInt Int
h (forall a b. (Integral a, Num b) => a -> b
fromIntegral @a @Int a
d)) Vector a
v
SBool (IntegralTypes a)
SFalse ->
case forall a. SBoolI (FloatingTypes a) => SBool (FloatingTypes a)
sFloating @a of
SBool (FloatingTypes a)
STrue ->
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm (\Int
h a
d -> Int -> Double -> Int
mixDouble Int
h (a -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac a
d :: Double)) Vector a
v
SBool (FloatingTypes a)
SFalse ->
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm Int -> a -> Int
forall a. Show a => Int -> a -> Int
mixShow Vector a
v
BoxedColumn Maybe Bitmap
bm (Vector a
v :: V.Vector a) ->
case TypeRep a -> TypeRep Text -> Maybe (a :~: Text)
forall a b. TypeRep a -> TypeRep b -> Maybe (a :~: b)
forall {k} (f :: k -> *) (a :: k) (b :: k).
TestEquality f =>
f a -> f b -> Maybe (a :~: b)
testEquality (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @a) (forall a. Typeable a => TypeRep a
forall {k} (a :: k). Typeable a => TypeRep a
typeRep @T.Text) of
Just a :~: Text
Refl -> IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> Text -> Int)
-> Vector Text
-> IO ()
forall a.
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
boxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
bm Int -> Text -> Int
mixText Vector a
Vector Text
v
Maybe (a :~: Text)
Nothing -> IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
forall a.
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
boxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
bm Int -> a -> Int
forall a. Show a => Int -> a -> Int
mixShow Vector a
v
PackedText Maybe Bitmap
bm PackedTextData
p -> IOVector Int
-> Int -> Int -> Maybe Bitmap -> PackedTextData -> IO ()
packedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
bm PackedTextData
p
unboxedRange ::
(VU.Unbox a) =>
VUM.IOVector Int ->
Int ->
Int ->
Maybe Bitmap ->
(Int -> a -> Int) ->
VU.Vector a ->
IO ()
unboxedRange :: forall a.
Unbox a =>
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
unboxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
ubm Int -> a -> Int
mix Vector a
v = Int -> IO ()
go Int
lo
where
go :: Int -> IO ()
go !Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
hi = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
Int
h <- MVector (PrimState IO) Int -> Int -> IO Int
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m a
VUM.unsafeRead IOVector Int
MVector (PrimState IO) Int
mv Int
i
let !h' :: Int
h' = case Maybe Bitmap
ubm of
Just Bitmap
bm | Bool -> Bool
not (Bitmap -> Int -> Bool
bitmapTestBit Bitmap
bm Int
i) -> Int -> Int -> Int
mixInt Int
h Int
nullSalt
Maybe Bitmap
_ -> Int -> a -> Int
mix Int
h (Vector a -> Int -> a
forall a. Unbox a => Vector a -> Int -> a
VU.unsafeIndex Vector a
v Int
i)
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
mv Int
i Int
h'
Int -> IO ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINE unboxedRange #-}
boxedRange ::
VUM.IOVector Int ->
Int ->
Int ->
Maybe Bitmap ->
(Int -> a -> Int) ->
V.Vector a ->
IO ()
boxedRange :: forall a.
IOVector Int
-> Int
-> Int
-> Maybe Bitmap
-> (Int -> a -> Int)
-> Vector a
-> IO ()
boxedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
bm Int -> a -> Int
mix Vector a
v = Int -> IO ()
go Int
lo
where
go :: Int -> IO ()
go !Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
hi = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
Int
h <- MVector (PrimState IO) Int -> Int -> IO Int
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m a
VUM.unsafeRead IOVector Int
MVector (PrimState IO) Int
mv Int
i
let !h' :: Int
h' = case Maybe Bitmap
bm of
Just Bitmap
bm' | Bool -> Bool
not (Bitmap -> Int -> Bool
bitmapTestBit Bitmap
bm' Int
i) -> Int -> Int -> Int
mixInt Int
h Int
nullSalt
Maybe Bitmap
_ -> Int -> a -> Int
mix Int
h (Vector a -> Int -> a
forall a. Vector a -> Int -> a
V.unsafeIndex Vector a
v Int
i)
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
mv Int
i Int
h'
Int -> IO ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINE boxedRange #-}
packedRange ::
VUM.IOVector Int ->
Int ->
Int ->
Maybe Bitmap ->
PackedTextData ->
IO ()
packedRange :: IOVector Int
-> Int -> Int -> Maybe Bitmap -> PackedTextData -> IO ()
packedRange IOVector Int
mv Int
lo Int
hi Maybe Bitmap
bm PackedTextData
p =
case PackedTextData -> Maybe PackedSel
ptSel PackedTextData
p of
Maybe PackedSel
Nothing -> Array -> PackedOffsets -> IO ()
contiguous (PackedTextData -> Array
ptBytes PackedTextData
p) (PackedTextData -> PackedOffsets
ptOffsets PackedTextData
p)
Just PackedSel
_ -> IO ()
selected
where
valid :: Int -> Bool
valid Int
i = case Maybe Bitmap
bm of
Just Bitmap
bm' -> Bitmap -> Int -> Bool
bitmapTestBit Bitmap
bm' Int
i
Maybe Bitmap
Nothing -> Bool
True
contiguous :: Array -> PackedOffsets -> IO ()
contiguous !Array
arr !PackedOffsets
offs = Int -> IO ()
go Int
lo
where
go :: Int -> IO ()
go !Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
hi = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
Int
h <- MVector (PrimState IO) Int -> Int -> IO Int
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m a
VUM.unsafeRead IOVector Int
MVector (PrimState IO) Int
mv Int
i
let !o :: Int
o = PackedOffsets -> Int -> Int
offAt PackedOffsets
offs Int
i
!l :: Int
l = PackedOffsets -> Int -> Int
offAt PackedOffsets
offs (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
o
!h' :: Int
h' = if Int -> Bool
valid Int
i then Int -> Array -> Int -> Int -> Int
mixBytes Int
h Array
arr Int
o Int
l else Int -> Int -> Int
mixInt Int
h Int
nullSalt
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
mv Int
i Int
h'
Int -> IO ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
selected :: IO ()
selected = Int -> IO ()
go Int
lo
where
go :: Int -> IO ()
go !Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
hi = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
| Bool
otherwise = do
Int
h <- MVector (PrimState IO) Int -> Int -> IO Int
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> m a
VUM.unsafeRead IOVector Int
MVector (PrimState IO) Int
mv Int
i
let !h' :: Int
h' =
if Int -> Bool
valid Int
i
then let (Array
arr, Int
o, Int
l) = PackedTextData -> Int -> (Array, Int, Int)
packedSlice PackedTextData
p Int
i in Int -> Array -> Int -> Int -> Int
mixBytes Int
h Array
arr Int
o Int
l
else Int -> Int -> Int
mixInt Int
h Int
nullSalt
MVector (PrimState IO) Int -> Int -> Int -> IO ()
forall (m :: * -> *) a.
(PrimMonad m, Unbox a) =>
MVector (PrimState m) a -> Int -> a -> m ()
VUM.unsafeWrite IOVector Int
MVector (PrimState IO) Int
mv Int
i Int
h'
Int -> IO ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
{-# INLINE packedRange #-}