haskell - 具有快速随机性和纯度的并行计算?

标签 haskell random parallel-processing

我的目标是使用 parMap 并行计算来自 parallel package ,但我还想为我的采样函数添加一些随机性。

如果没有随机性,我的计算只是一些数字运算,所以它是纯粹的,我可以使用 parMap .为了得到好的结果,我需要在每一步都取多个样本并对结果进行平均。抽样需要随机化。

一种解决方案可能是使用 random package , 调用randoms然后在计算过程中使用该列表(通过将纯惰性列表传递给计算,我将保持其纯净)。不幸的是,这是一个非常慢的随机数生成器,我需要很多随机数,所以我更愿意使用 mwc-randommersenne-random (虽然,我不认为 mersenne-random 仍然保持不变)。

使用 unsafePerformIO 之类的内容是否安全?用 mwc-random 写一个类似 randoms 的函数?像这样的东西:

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)

我是否需要转而使用 parallel number generator ?或者我是否需要硬着头皮承认如果不使用慢速随机包我的算法根本不纯?

建议?谢谢!

最佳答案

如果具有单线程随机源对性能来说不是问题,您可以获得 mwc-random 的纯包装器

import Control.Monad.ST.Lazy
import Control.Monad
import System.Random.MWC

rList :: Variate a => Seed -> [a]
rList s = runST $ do
  g <- strictToLazyST $ restore s
  advance g

advance :: Variate a => Gen s -> ST s [a]
advance g = do
  x <- strictToLazyST $ uniform g
  xs <- x `seq` advance g
  return (x:xs)

这里 rList取一个种子,然后确定性地懒惰地产生无限的懒惰数流。我不确定 strictToLazyST确实很安全,但似乎没有人反对。我没有做任何基准测试,但我怀疑这相当快。我假设 mwc-random由于使用生成器编码的 explit 数据流是线程安全的,并且它可以在 ST 中使用单子(monad)。邀请某人使用上面的 hack。我不认为 seq是必要的,但它让我对 strictToLazyST 不那么怀疑了我知道我有确定性的评估顺序(它仍然懒得工作)。

您仍然需要随机性(即 IO )在某处生成真正的随机种子,但这应该让您保持大部分代码纯净,并让您将种子存储到文件中或在必要时重用它。

GHCI:
λ: gen <- create
λ: x <- save gen
λ: drop 1 $ take 10 $ rList x :: [Int]
[4443157817804305558,-6283633474236987377,3602072957429409483,
 -5035101780705339502,-925260411398682800,423158235494603307,
 -6981326876987356147,490540715145304360,-8184987036354194323]

关于haskell - 具有快速随机性和纯度的并行计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16248600/

相关文章:

c# - 如何随机生成1000个6位数字序列

不调用 MPI_Comm_create_keyval 中提供的回调

java - 我应该尽可能使用并行流吗?

arrays - 如何从函数创建 Haskell 数组

haskell - 安装 leksah 的异常

haskell - "error"函数的存在如何影响 Haskell 的纯度?

algorithm - 将 rand5 映射到范围内的数字

haskell - 多参数一元绑定(bind)

javascript - Math.random() 的概率修饰符

Java 11 从 8 个并行流升级引发 ClassNotFoundException