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.