次のコードは、 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ます。deepSeqArrayの定義でを使用してみましたfmapTが、役に立ちません。テストは独立しているため (ランダム性の順序付けは別として)、この例でネストされた並列処理がどのように可能であるかは明確ではありません。
興味深いことに、mainjust に変更するとquickCheck prop_fmap、100 回のテストが正常に完了します。そのため、テスト フレームワーク (おそらくモナド シーケンスのより一般的な問題) とは異なる何かが起こっているようですQuickCheck。
このエラーが発生する理由と、並列計算を実行しながらエラーを回避する方法についてのアイデアはありますか?