Производительность Repa 3 и правильное использование «сейчас»

Здесь есть базовый вопрос о монаде, не связанный с Repa, плюс несколько вопросов, специфичных для Repa.

Я работаю над библиотекой, используя Repa3. У меня проблемы с получением эффективного параллельного кода. Если я заставлю свои функции возвращать массивы с задержкой, я получу мучительно медленный код, который очень хорошо масштабируется до 8 ядер. Этот код занимает более 20 ГБ памяти на профилировщик GHC и работает на несколько порядков медленнее, чем базовые неупакованные векторы Haskell.

В качестве альтернативы, если я заставлю все свои функции возвращать распакованные массивы манифеста (все еще пытаясь использовать слияние внутри функций, например, когда я делаю «карту»), я получаю НАМНОГО более быстрый код (все еще медленнее, чем при использовании распакованных векторов Haskell). ), который вообще не масштабируется и фактически имеет тенденцию становиться немного медленнее с большим количеством ядер.

Судя по коду примера БПФ в Repa-Algorithms, правильный подход заключается в том, чтобы всегда возвращать массивы манифеста. Есть ли когда-нибудь случай, когда я должен возвращать задержанные массивы?

Код БПФ также широко использует функцию «сейчас». Однако я получаю ошибку типа, когда пытаюсь использовать его в своем коде:

type Arr t r = Array t DIM1 r
data CycRingRepa m r = CRTBasis (Arr U r)
                     | PowBasis (Arr U r)

fromArray :: forall m r t. (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r
fromArray = 
    let mval = reflectNum (Proxy::Proxy m)
    in \x ->
        let sh:.n = extent x
        in assert (mval == 2*n) PowBasis $ now $ computeUnboxedP $ bitrev x

Код прекрасно компилируется без «сейчас». С «сейчас» я получаю следующую ошибку:

Не удалось сопоставить тип r с Массив U (Z :.инт) р' `r' - это переменная жесткого типа, связанная сигнатура типа для fromArray :: (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r в C:\Users\crokeea\Documents\Code\LatticeLib\CycRingRepa.hs:50:1 Ожидаемый тип: CycRingRepa m r Фактический тип: CycRingRepa m (Array U DIM1 r)

Я не не думаючто это моя проблема. Было бы полезно, если бы кто-нибудь объяснил, как работает монада «сейчас». По моим лучшим оценкам, монада, кажется, создает «Arr U (Arr U r)». Я ожидаю «Arr U r», который затем будет соответствовать шаблону конструктора данных. Что происходит и как это исправить?

Ниже приведены сигнатуры типов:

computeUnboxedP :: Fill r1 U sh e => Array r1 sh e -> Array U sh e
now :: (Shape sh, Repr r e, Monad m) => Array r sh e -> m (Array r sh e)

Было бы полезно иметь лучшее представление о том, когда уместно использовать «сейчас».

Еще пара вопросов от Репа: Должен ли я явно вызывать calculateUnboxedP (как в примере кода БПФ) или использовать более общий ComputeP (поскольку распаковываемая часть определяется моим типом данных)? Должен ли я хранить отложенные массивы или массивы манифеста в типе данных CycRingRepa? В конце концов я также хотел бы, чтобы этот код работал с целыми числами Haskell.Потребует ли это от меня написания нового кода, который использует что-то другое, кроме U-массивов, или я могу написать полиморфный код, который создает U-массивы для распакованных типов и какой-то другой массив для целых/упакованных типов?

Я понимаю, что здесь много вопросов, и я ценю любые ответы!

15
задан Community 23 May 2017 в 12:11
поделиться