Здесь есть основной монадный вопрос, не связанный с Repa, плюс несколько специфических для Repa вопросов.
Я работаю над библиотекой, использующей Repa3. У меня проблемы с получением эффективного параллельного кода. Если я заставлю свои функции возвращать отложенные массивы, я получу мучительно медленный код, который очень хорошо масштабируется до 8 ядер. Этот код занимает более 20 ГБ памяти на профилировщик GHC и работает на несколько порядков медленнее, чем базовые распакованные векторы Haskell.
В качестве альтернативы, если я заставлю все мои функции возвращать массивы манифестов без коробок (все еще пытаюсь использовать слияние внутри функций, например, когда я делаю 'map'), я получаю НАМНОГО более быстрый код (все же медленнее, чем использование незаписанных векторов Haskell ), который вообще не масштабируется, и на самом деле имеет тенденцию становиться немного медленнее с большим количеством ядер.
Основываясь на примере кода FFT в Repa-Algorithms, кажется, что правильный подход - всегда возвращать манифестные массивы. Был ли когда-нибудь случай, когда я должен был возвращать отложенные массивы?
Код FFT также широко использует функцию «сейчас». Тем не менее, я получаю сообщение об ошибке типа при попытке использовать его в моем коде:
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' with
Array U (Z:. Int) r '
'r' - это переменная жесткого типа, связанная
подпись типа для
fromArray :: (BaseRing m r, Unbox r, Repr t r) =>
Arr t r -> CycRingRepa m r
в C: \ Users \ crockeea \ 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)
Было бы полезно иметь лучшее представление о том, когда целесообразно использовать «сейчас».
Пара других вопросов Repa:
Должен ли я явно вызывать computeUnboxedP (как в примере кода FFT), или я должен использовать более общий computeP (потому что часть unbox определяется моим типом данных)?
Должен ли я хранить отложенные или явные массивы в типе данных CycRingRepa?
В конце концов я также хотел бы, чтобы этот код работал с Haskell Integers. Потребуется ли мне писать новый код, который использует что-то отличное от U-массивов, или я могу написать полиморфный код, который создает U-массивы для типов unbox и некоторый другой массив для целочисленных / коробочных типов?
Я понимаю, что здесь много вопросов, и я ценю любые / все ответы!