gpt4 book ai didi

.net - F# 中的线程安全普通随机数生成器

转载 作者:行者123 更新时间:2023-12-04 17:11:35 25 4
gpt4 key购买 nike

需要一个从正态(高斯)分布返回样本的随机数生成器,我已将 John D. Cook's C# generator 的一部分移植到 F# :

let mutable m_w = 521288629u
let mutable m_z = 362436069u

let private getUint () =
m_z <- 36969u * (m_z &&& 65535u) + (m_z >>> 16)
m_w <- 18000u * (m_w &&& 65535u) + (m_w >>> 16)
(m_z <<< 16) + m_w

let private setSeed () =
let dt = System.DateTime.Now
let x = dt.ToFileTime ()
m_w <- uint32 (x >>> 16)
m_z <- uint32 (x % 4294967296L)

let private getUniform () =
let u = getUint ()
(float u + 1.) * 2.328306435454494e-10

let private randomNormal () =
let u1 = getUniform ()
let u2 = getUniform ()
let r = sqrt (-2. * (log u1))
let theta = 2. * System.Math.PI * u2
r * sin (theta)

/// Returns a normal (Gaussian) random sample with mean 0 and standard deviation 1
let randn () =
setSeed ()
randomNormal ()

/// Returns an array of normal (Gaussian) random samples
let randns n m =
setSeed ()
[| for i in 0 .. n - 1 -> randomNormal () |]

此实现工作正常,但不是线程安全的。鉴于依赖于它的代码广泛使用了线程并行库,我需要使其成为线程安全的。

这对我来说看起来并不明显,因为该方法的核心是两个几乎不可或缺的可变成员。有没有其他方法可以在不使用锁的情况下实现线程安全?

有没有其他方法可以仅使用不可变成员来实现普通的伪随机生成器?

最佳答案

使用可变成员,您别无选择,只能使用锁。

但是,最好使用不可变的 record包含 m_wm_z你传递给你的随机函数。他们可以返回您的随机值的元组和包含更新的随机成员的新​​记录。更好的是,您可以创建一个 computation expression处理生成随机数,因此您不必担心传递随机记录。

另外,调用setSeed从你的随机函数中是不好的。多个后续调用将返回相同的值。您只想设置一次种子。

关于.net - F# 中的线程安全普通随机数生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10417123/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com