Skip to content

Conversation

@tomsmeding
Copy link
Member

In accelerate 1.3, code that should have been dead-code eliminated, but was not, may be executed at runtime while nothing waits for it. The fact that this is possible makes fromPtrs essentially impossible to use safely.

In accelerate 1.3, code that should have been dead-code eliminated, but
was not, may be executed at runtime while nothing waits for it. The fact
that this is possible makes fromPtrs essentially impossible to use
safely.
@tomsmeding
Copy link
Member Author

Reproduction for the issue in question:

{-# LANGUAGE RankNTypes #-}
module FromPtrsUnsafe where

import qualified Data.Array.Accelerate as A
import Data.Array.Accelerate.Array.Unique (newUniqueArray)
import qualified Data.Array.Accelerate.Representation.Array as R
import Data.Array.Accelerate.Sugar.Array (Array(..))
import Data.Array.Accelerate.Test.NoFib.Base

import Control.Monad
import Foreign
import Test.Tasty
import Test.Tasty.HUnit

-- Source: reduced from https://github.com/LCSB-BioCore/remotesom/blob/516581a3e2973a5561a08b0abcffbb9d7afb261e/Numeric/RemoteSOM.hs
somIter :: A.Acc (A.Matrix Float) -> A.Acc (A.Matrix Float) -> A.Acc (A.Matrix Float)
somIter points som =
  let A.I2 ptsn _ = A.shape points
      A.I2 somn dim = A.shape som
      closest = A.generate (A.I1 ptsn) $ \_ -> 0
      A.T2 s _s = A.T2 
                    (A.permute
                      (+)
                      (A.I2 somn dim `A.fill` A.constant (0 :: Float))
                      (\(A.I2 pix dimi) -> A.Just_ $ A.I2 (closest A.! A.I1 pix) dimi)
                      points)
                    (A.permute
                      (+)
                      (A.I2 somn dim `A.fill` A.constant (0 :: Float))
                      (\(A.I2 pix dimi) -> A.Just_ $ A.I2 (closest A.! A.I1 pix) dimi)
                      (A.map (\x -> x * x) points))
  in s

test_fromPtrsUnsafe :: RunN -> TestTree
test_fromPtrsUnsafe runN = testCase "fromPtrsUnsafe" $ do
  let ptsn = 200000
      dim = 128

  pointsbuf <- mallocBytes (ptsn * dim * sizeOf (undefined :: Float))
  forM_ [0 .. ptsn*dim - 1] $ \i ->
    pokeElemOff pointsbuf i 0.0
  pointsUA <- newUniqueArray =<< newForeignPtr_ pointsbuf
  let points = Array (R.Array (((), ptsn), dim) pointsUA)

  let som = A.fromFunction (A.Z A.:. 400 A.:. dim) (\_ -> 0.0)
  let res = runN somIter points som
  when (res /= A.fromFunction (A.Z A.:. 400 A.:. dim) (\_ -> 0.0)) $
    assertFailure "unequal"

  free pointsbuf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant