Вложенный параллелизм в Repa

Следующий код выдает (ужасную) ошибку «вложенного параллелизма» с 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, но это не помогает. Поскольку тесты независимы (помимо последовательности случайности), неясно, как вообще возможен вложенный параллелизм в этом примере.

Интересно, что если я изменю main только на quickCheck prop_fmap, он успешно завершит 100 тестов. Итак, похоже, что-то происходит с тестовой структурой (вероятно, более общая проблема с последовательностью монад), которая отличается от QuickCheck.

Любые идеи о том, почему я получаю эту ошибку и как ее избежать, продолжая выполнять параллельные вычисления?

Примечание. Использование монады Identity: ref1, ref2


person crockeea    schedule 07.10.2015    source источник
comment
Может ли это быть связано с Что не так с использованием монады Identity с mmultP при использовании repa?   -  person Petr    schedule 16.06.2016
comment
@PetrPudlák Я думаю, что проблема в данном случае в том, что test-framework является многопоточным. Это определенно приводит к вложенному параллелизму. Спасибо, что напомнили мне об этом вопросе!   -  person crockeea    schedule 16.06.2016


Ответы (1)


Проблема в том, что test-framework неявно является многопоточным (см. ="nofollow">это например.)

Решение, которое работает для меня, — запустить defaultMainWithArgs с параметром --threads=1.

person crockeea    schedule 16.06.2016
comment
Означает ли это, что Repa нельзя вызывать из параллельных потоков? Мне это кажется странным, возможно, есть другой способ. - person Petr; 16.06.2016
comment
@PetrPudlák Я спросил Бена Липпмайера: возможен ли крупнозернистый параллелизм при использовании repa? Его ответ в частном сообщении: Модель параллельных данных предполагает один поток управления. Также предполагается, что имеется достаточно работы для использования всех процессоров. Одновременный запуск двух вычислений repa ничего не ускорит и не поддерживается библиотекой. В лучшем случае вы просто понесете больше накладных расходов при планировании, поэтому я добавил предупреждение [о вложенном параллелизме]. - person crockeea; 16.06.2016