Istnieje tutaj podstawowe pytanie dotyczące monady, niezwiązane z Repa, oraz kilka pytań specyficznych dla Repa.Repa 3 wydajność i poprawne użycie "teraz"
Pracuję nad biblioteką przy użyciu Repa3. Mam problem z uzyskaniem wydajnego kodu równoległego. Jeśli sprawię, że moje funkcje zwrócą tablice opóźnione, otrzymuję niesamowicie powolny kod, który skaluje się bardzo dobrze do 8 rdzeni. Ten kod zajmuje ponad 20 GB pamięci na profiler GHC i przebiega o kilka rzędów wielkości wolniej niż podstawowe nieskrytowane wektory Haskella. Alternatywnie, jeśli wszystkie moje funkcje zwrócą się do niezapakowanych tablic manifestów (nadal próbuję użyć fuzji w ramach funkcji, na przykład gdy wykonuję "mapę"), otrzymam DUŻO szybszego kodu (nadal wolniej niż przy użyciu rozpakowanego Haskella). wektory), które nie skalują się w ogóle, a w rzeczywistości wydają się nieco wolniejsze z większą liczbą rdzeni.
W oparciu o przykładowy kod FFT w algorytmach Repa, wydaje się, że właściwym podejściem jest zawsze zwracanie manifestu tablic. Czy jest kiedykolwiek przypadek, w którym powinienem zwrócić opóźnione tablice?
Kod FFT umożliwia także korzystanie z funkcji "teraz". Jednak pojawia się błąd typu, gdy próbuję go użyć w moim kodzie:
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
Kod kompiluje dobrze bez "teraz". Z „teraz”, pojawia się następujący błąd:
Couldn't match type
r' with
Array U (Z :. Int) r' `r' is a rigid type variable bound by the type signature for fromArray :: (BaseRing m r, Unbox r, Repr t r) => Arr t r -> CycRingRepa m r at C:\Users\crockeea\Documents\Code\LatticeLib\CycRingRepa.hs:50:1 Expected type: CycRingRepa m r Actual type: CycRingRepa m (Array U DIM1 r)
ja nie myślećthis jest mój problem. Byłoby pomocne, gdyby ktoś mógł wyjaśnić, w jaki sposób Monada działa w "teraz". Według mojej najlepszej oceny, monada wydaje się tworzyć "Arr U (Arr U r)". Spodziewam się "Arr U r", który będzie wtedy pasował do wzorca konstruktora danych. Co się dzieje i jak to naprawić?
Podpisy typu są:
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)
Byłoby pomocne mieć lepsze wyobrażenie o tym, kiedy należy użyć „teraz”.
Kilka innych pytań Repa: Czy mogę jawnie wywołać computeUnboxedP (jak w przykładowym kodzie FFT), czy też powinienem użyć bardziej ogólnego computeP (ponieważ część unbox jest wywnioskowana według mojego typu danych)? Czy należy przechowywać opóźnione lub jawne tablice w typie danych CycRingRepa? Ostatecznie chciałbym również, aby ten kod działał z Integerami Haskella. Czy będzie to wymagało napisania nowego kodu, który będzie wykorzystywał coś innego niż tablice U, czy mogę napisać kod polimorficzny, który tworzy tablice U dla typów unbox i jakiejś innej tablicy dla liczb całkowitych/typów pudełkowych?
Zdaję sobie sprawę, że jest tu wiele pytań i doceniam wszystkie/wszystkie odpowiedzi!