massiv icon indicating copy to clipboard operation
massiv copied to clipboard

Stencil with self dependency and waterfall parallelization

Open lehins opened this issue 5 years ago • 0 comments

Recently there was a request on dataHaskell gitter about creating an array in parallel, where generation of an array element depends on some of its neighbors. Here is a solution for 2D matrices:

waterfallCreate ::
     Mutable r Ix2 a => Sz2 -> (Maybe a -> Maybe a -> a) -> (a -> a -> a) -> Array r Ix2 a
waterfallCreate sz@(Sz2 m n) g f =
  unsafePerformIO $
  createArray_ Par sz $ \scheduler marr -> do
    void $ write marr (0 :. 0) $ g Nothing Nothing
    forM_ (1 ..: m) $ \i ->
      unsafeWrite marr (i :. 0) . g Nothing . Just =<< unsafeRead marr (i - 1 :. 0)
    forM_ (1 ..: n) $ \j -> do
      unsafeWrite marr (0 :. j) . (`g` Nothing) . Just  =<< unsafeRead marr (0 :. j - 1)
      let jIter = rangeStepSize Seq j (-1) (Sz (min (m - 1) j))
      iforSchedulerM_ scheduler jIter $ \i' -> writeF marr (i' + 1)
    forM_ (2 ..: m) $ \i -> do
      let jIter = rangeStepSize Seq (n - 1) (-1) (Sz (min (n - 1) (m - i)))
      iforSchedulerM_ scheduler jIter $ \i' -> writeF marr (i' + i)
  where
    writeF marr i j = do
      left <- unsafeRead marr (i :. j - 1)
      top <- unsafeRead marr (i - 1 :. j)
      unsafeWrite marr (i :. j) $ f left top
    {-# INLINE writeF #-}
{-# INLINE waterfallCreate #-}

Above solution is a good demonstration of the problem, but the full solution will require:

  • support for arbitrary dimensions
  • ability to select which neighbors there is a dependency on
  • implemented as a stencil, not only for creation of new arrays
  • use same optimizations as in DW array
  • block wise parallelization along the diagonal, instead of single element diagonal.

lehins avatar Nov 26 '19 13:11 lehins