Repa 中的嵌套并行
Nested Parallelism in Repa
以下代码会产生(可怕的)"nested parallelism" 错误 repa-3.4.0.1:
import Control.Monad.Identity (runIdentity, liftM)
import Data.Array.Repa as R
import Data.Array.Repa.Repr.Unboxed
import Data.Vector.Unboxed
import Test.Framework
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck hiding (generate,output)
main :: IO ()
main = defaultMainWithArgs [prop,prop] ["--maximum-generated-tests=1"]
prop = testProperty "Test" $ property prop_fmap
prop_fmap :: Arr Int -> Bool
prop_fmap x = fmapT id x == x
newtype Arr r = Arr (Array U DIM1 r) deriving (Eq, Show)
instance (Arbitrary r, Unbox r) => Arbitrary (Arr r) where
arbitrary = replM arbitrary
shrink = shrinkNothing
replM :: (Unbox r, Monad mon) => mon r -> mon (Arr r)
replM = let n = 6
in liftM (Arr . fromUnboxed (Z:.n)) . replicateM n
fmapT :: (Unbox a, Unbox b) => (a -> b) -> Arr a -> Arr b
fmapT f (Arr v) = Arr $ force' $ R.map f $ v
force' :: (Shape sh, Unbox r) => Array D sh r -> Array U sh r
force' = runIdentity . computeP
准确的错误是:
Performing nested parallel computation sequentially. You've probably
called the 'compute' or 'copy' function while another instance was
already running. This can happen if the second version was suspended
due to lazy evaluation. Use 'deepSeqArray' to ensure that each array
is fully evaluated before you 'compute' the next one.
我正在使用 ghc Main -threaded
和 运行 Main +RTS -N2
进行编译。我试过在 fmapT
的定义中使用 deepSeqArray
,但没有用。由于测试是独立的(除了随机性排序之外),因此不清楚本例中嵌套并行性如何成为可能。
有趣的是,如果我将 main
更改为 quickCheck prop_fmap
,它会成功完成 100 次测试。因此,测试框架似乎发生了一些与 QuickCheck
.
不同的事情(可能是 monad 排序的更普遍的问题)
关于为什么我会收到此错误以及如何在仍在进行并行计算的同时避免它的任何想法?
注意:使用 Identity
monad:ref1, ref2
问题是 test-framework
是隐式多线程的(例如参见 [=13=]。)
对我有用的解决方案是 运行 defaultMainWithArgs
和选项 --threads=1
.
以下代码会产生(可怕的)"nested parallelism" 错误 repa-3.4.0.1:
import Control.Monad.Identity (runIdentity, liftM)
import Data.Array.Repa as R
import Data.Array.Repa.Repr.Unboxed
import Data.Vector.Unboxed
import Test.Framework
import Test.Framework.Providers.QuickCheck2
import Test.QuickCheck hiding (generate,output)
main :: IO ()
main = defaultMainWithArgs [prop,prop] ["--maximum-generated-tests=1"]
prop = testProperty "Test" $ property prop_fmap
prop_fmap :: Arr Int -> Bool
prop_fmap x = fmapT id x == x
newtype Arr r = Arr (Array U DIM1 r) deriving (Eq, Show)
instance (Arbitrary r, Unbox r) => Arbitrary (Arr r) where
arbitrary = replM arbitrary
shrink = shrinkNothing
replM :: (Unbox r, Monad mon) => mon r -> mon (Arr r)
replM = let n = 6
in liftM (Arr . fromUnboxed (Z:.n)) . replicateM n
fmapT :: (Unbox a, Unbox b) => (a -> b) -> Arr a -> Arr b
fmapT f (Arr v) = Arr $ force' $ R.map f $ v
force' :: (Shape sh, Unbox r) => Array D sh r -> Array U sh r
force' = runIdentity . computeP
准确的错误是:
Performing nested parallel computation sequentially. You've probably
called the 'compute' or 'copy' function while another instance was
already running. This can happen if the second version was suspended
due to lazy evaluation. Use 'deepSeqArray' to ensure that each array
is fully evaluated before you 'compute' the next one.
我正在使用 ghc Main -threaded
和 运行 Main +RTS -N2
进行编译。我试过在 fmapT
的定义中使用 deepSeqArray
,但没有用。由于测试是独立的(除了随机性排序之外),因此不清楚本例中嵌套并行性如何成为可能。
有趣的是,如果我将 main
更改为 quickCheck prop_fmap
,它会成功完成 100 次测试。因此,测试框架似乎发生了一些与 QuickCheck
.
关于为什么我会收到此错误以及如何在仍在进行并行计算的同时避免它的任何想法?
注意:使用 Identity
monad:ref1, ref2
问题是 test-framework
是隐式多线程的(例如参见 [=13=]。)
对我有用的解决方案是 运行 defaultMainWithArgs
和选项 --threads=1
.