module Vision.Image.Parallel (computeP) where
import Control.Concurrent (
forkIO, getNumCapabilities, newEmptyMVar, putMVar, takeMVar)
import Control.Monad.ST (ST, stToIO)
import Data.Vector (enumFromN, forM, forM_)
import Foreign.Storable (Storable)
import System.IO.Unsafe (unsafePerformIO)
import Vision.Image.Class (MaskedImage (..), Image (..), (!))
import Vision.Image.Type (Manifest (..))
import Vision.Image.Mutable (MutableManifest, linearWrite, new, unsafeFreeze)
import Vision.Primitive (Z (..), (:.) (..), ix2)
computeP :: (Monad m, Image i, Storable (ImagePixel i))
=> i -> m (Manifest (ImagePixel i))
computeP !src =
return $! unsafePerformIO $ do
dst <- stToIO newManifest
childs <- forM (enumFromN 0 nCapabilities) $ \c -> do
child <- newEmptyMVar
_ <- forkIO $ do
let nLines | c == 0 = nLinesPerThread + remain
| otherwise = nLinesPerThread
stToIO $ fillFromN dst (c * nLinesPerThread) nLines
putMVar child ()
return child
forM_ childs takeMVar
stToIO $ unsafeFreeze dst
where
!size@(Z :. h :. w) = shape src
!nCapabilities = unsafePerformIO getNumCapabilities
!(nLinesPerThread, remain) = h `quotRem` nCapabilities
fillFromN !dst !from !n =
forM_ (enumFromN from n) $ \y -> do
let !lineOffset = y * w
forM_ (enumFromN 0 w) $ \x -> do
let !offset = lineOffset + x
!val = src ! (ix2 y x)
linearWrite dst offset val
newManifest :: Storable p => ST s (MutableManifest p s)
newManifest = new size