Moim celem jest zrównoleglenie obliczeń przy użyciu parMap
z parallel package, ale chciałbym również dodać trochę losowości do mojej funkcji próbkowania.Obliczenia równoległe z dużą losowością i czystością?
Bez losowości moje obliczenia są po prostu chrupaniem numerów, więc jest czysto i mogę użyć parMap
. Aby uzyskać dobre wyniki, muszę pobrać wiele próbek na każdym etapie i uzyskać średnie wyniki. Pobieranie próbek musi być losowe.
Jednym z rozwiązań może być użycie random package, wywołanie randoms
, a następnie skonsumowanie tej listy podczas obliczeń (przekazując czystą leniwą listę do obliczeń, które utrzymam w czystości). Niestety, jest to bardzo wolny generator liczb losowych i potrzebuję dużej liczby liczb losowych, więc wolałbym użyć albo mwc-random lub mersenne-random (chociaż, nie sądzę, że losy mersenne są nadal utrzymywane).
Czy można bezpiecznie używać czegoś takiego jak unsafePerformIO
z mwc-random, aby napisać funkcję podobną do randoms
? Coś takiego:
randomsMWC :: Variate a => GenST s -> [a]
randomsMWC g = unsafePerformIO $ unsafeSTToIO $ randomsMWC' g
where
randomsMWC' g = do
a <- uniform g
as <- unsafeInterleaveST $ randomsMWC' g
return (a : as)
Czy muszę zamiast tego sięgnąć po numer parallel number generator? Czy muszę ugryźć kulę i przyznać, że mój algorytm nie jest po prostu czysty bez użycia powolnego losowego pakietu?
Sugestie? Dzięki!
Mersenne-random-pure64 jest zarówno szybkie i pozwala na wiele generatorów - więc możesz mieć jeden na wątek. –
@DonStewart Wiele generatorów jest całkowicie bezużyteczne dla równoległego haskell.Nie ma możliwości wykorzystania zasobów specyficznych dla wątków z kodu równoległego, a nie powinno być - wprowadziłoby to niedeterminizm. To naprawdę trudny problem. – Carl
Carl - nie tak. Możesz duplikować losowe rany w sposób równoległy do danych, unikając rywalizacji na wspólnym zasobie. Pomyśl na przykład o redukcji w strukturze drzewa. –