生成具有恒定堆栈空间的随机向量

Posted

技术标签:

【中文标题】生成具有恒定堆栈空间的随机向量【英文标题】:Generating random vectors with constant stack space 【发布时间】:2013-11-13 05:59:07 【问题描述】:

我正在使用 Don Stewart 的 System.Random.Mersenne.Pure64 和 Control.Monad.Mersenne.Random 包,它们通常非常快,并且是 supposed to help avoid common errors,就像使用非严格的状态单子一样。

尽管如此,我还是设法编写了一些代码,导致中等大向量的堆栈溢出。

import qualified Data.Vector.Unboxed as U
import Data.Int
import System.Random.Mersenne.Pure64
import Control.Monad.Mersenne.Random

main = do
    let dim = 1000000
        y = evalRandom (U.replicateM dim getInt64) (pureMT 13) :: U.Vector Int64
    putStr $ (show $ U.head y)

我猜这一定是由于 Vector 的 replicateM 实现的懒惰,虽然很难看到,因为它是使用 streams 实现的。

如何编写使用常量堆栈空间对大向量进行采样的代码?

【问题讨论】:

另外,我预计U.headU.tail 之一会在没有堆栈溢出的情况下打印,但事实并非如此。即使使用(希望)惰性盒装向量,这种行为仍然存在,这对我来说更出乎意料。 【参考方案1】:

monad-mersenne-random 没有立即明显的错误(没有查看核心一 iota),但值得注意的是,使用 state monad 时一切正常:

import Control.Monad.State

...

        y      = evalState (U.replicateM dim (state $ \s -> randomInt64 s)) (pureMT 13) :: U.Vector Int64

结果:

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.3
$ ghc so.hs -fforce-recomp
[1 of 2] Compiling Control.Monad.Mersenne.Random ( Control/Monad/Mersenne/Random.hs, Control/Monad/Mersenne/Random.o )
[2 of 2] Compiling Main             ( so.hs, so.o )
Linking so ...
$ ./so
-7188968464842378225

编辑:

查看两个 monad 定义(StateTRand),似乎唯一真正的区别在于元组的严格性。所以我尝试使用Control.Monad.State.Strict 和啊哈!堆栈溢出返回。所以我猜想埋在 Vector 的replicateM 代码中的代码类似于basereplicateM 中使用的foldr。这可以解释为什么您不希望序列严格。

【讨论】:

真的不值得“一无所有”,还是只值得“注意”? 好吧,如果你必须使用Rand monad,我想这毫无价值,但我的意思是“注意”。 ;-)

以上是关于生成具有恒定堆栈空间的随机向量的主要内容,如果未能解决你的问题,请参考以下文章

生成两个相关的随机向量

生成具有特定数量负数的随机向量

如何生成指向具有各向同性方向分布的随机方向的单位向量?

多维空间中的随机单位向量

std :: deque(双端队列)真的是随机访问和恒定时间插入吗?

随机向量 a 具有来自 R 中均匀分布的元素