#random #monte-carlo

no-std smolprng

使用Rust编写的轻量级且可扩展的伪随机数生成器

7个版本

0.1.6 2024年3月14日
0.1.5 2022年7月29日
0.1.4 2022年1月18日

#201 in 算法

Download history 7/week @ 2024-04-23 15/week @ 2024-05-07 3/week @ 2024-05-14 3/week @ 2024-05-21 9/week @ 2024-05-28 64/week @ 2024-07-30

每月64次下载
用于hercules

BSD-3-Clause

45KB
806

codecov unsafe forbidden crates.io

SmolPRNG

这是一个纯Rust编写的轻量级PRNG库/框架,是我另一个项目的翻译,即SmallPRNG。此项目的主要目标是实现尽可能多的功能,而是提供一个通用的框架,用于实现PRNG算法以测试蒙特卡洛代码。这主要是作为一个学习Rust及其功能的教程项目,但我希望这也可以用于像SmallPRNG一样的生产性项目。

为了符合“SmolPRNG”的名称,代码行数不到1000行,但开箱即提供了22多种算法,可以从15个统计分布中进行采样,包括所有代码、测试、文档和基准测试。

SmolPRNG的性能与Rand Rustcrate相当,但扩展性更简单。可以使用no_std功能来移除对标准库的依赖,但这是默认不启用的。在现代硬件上的编译时间约为.2秒。此包无论是否有std依赖都不会在堆上分配内存。要将在您的项目中包含此crate,您可以在您的Cargo.toml文件中使用以下内容。最新版本为0.1.6。

[dependencies]
smolprng = {version = "0.1.6", features = ["std"]}

要使用此包而不依赖std,您可以在您的Cargo.toml文件中使用以下内容。请注意,截至目前,关闭std依赖将删除大多数高级分布采样,但保留了均匀分布采样、伯努利、二项式和泊松分布。包含其他分布的主要限制是core库中缺少某些特殊函数(如lnsqrtsin等)。

[dependencies]
smolprng = {version = "0.1.6", features = ["no_std"]}

特性

  • 接口
  • PRNG算法
  • 生成无符号整数
  • 生成均匀的f32f64
  • 分布(正态、Beta、柯西、伯努利等)
  • 轻松初始化算法状态
  • 基准测试
  • TestU01验证

生成数字

在初始化PRNG对象后,生成随机数非常简单

let prng = PRNG{generator: JsfGenerator::default()};

let rand_bool = prng.gen_bool(); // Generates a random bool

let rand_u8 = prng.gen_u8();      //Generates a random u8
let rand_u16 = prng.gen_u16();    //Generates a random u16
let rand_u32 = prng.gen_u32();    //Generates a random u32
let rand_u64 = prng.gen_u64();    //Generates a random u64
let rand_u128 = prng.gen_u128();  //Generates a random u128

let rand_f32 = prng.gen_f32();    //Generates a random f32
let rand_f64 = prng.gen_f64();    //Generates a random f64

实现您自己的算法

以下是一个示例,通过在结构体上实现implAlgorithm特质来注入一个新算法生成伪随机数。可用的Outputs包括u8u16u32u64u128

struct StepGenerator{
  state: u32,
}

impl Algorithm for StepGenerator {
  type Output = u32;

  fn gen(&mut self) -> Self::Output {
    self.data = self.data.overflowing_add(1).0;
    self.data
  }
}

// somewhat gross macro, that adds the traits Iterator, Default, and From<U> where U in {u8, u16, u32, u64, u128}
prng_setup! {StepGenerator, StepGenerator, data, make_1_u32}

使用这个方法,我们可以创建一个

// create step generator state from output of SplitMix64 algorithm of a u32 seed
let step_generator = StepGenerator::from(12765u32); 
let prng = PRNG{generator: step_generator}

性能

以下是该包在英特尔12700k CPU上运行的性能概述。这被分为三个不同的基准测试,生成一个1024字节的随机数填充的缓冲区,求和100万个随机生成的f64,然后是100万个生成的f32。使用最快的Step生成器结果作为基线,因为这个算法是通过添加1并返回状态定义的。这是除了常数生成器之外最简单的算法。

这并不是详尽的,但为了覆盖性能特征的概貌。

生成1024字节缓冲区

时间 带宽
Step生成器 49ns 20.4 GB/s
Xoshiro256+ 87ns 11.5 GB/s
SplitMix64 92ns 10.9 GB/s
JSFLarge 105ns 9.5 GB/s

求和100万个随机生成的f32

时间 每个f32的时间
Step生成器 0.28 ms 0.28 ns
SCFSmall 0.51 ms 0.51 ns
Xoshiro256+ 0.61 ms 0.61 ns
SplitMix64 0.65 ms 0.65 ns
JSFLarge 0.83 ms 0.83 ns

求和100万个随机生成的f64

时间 每个f64的时间
Step生成器 0.32 ms 0.32 ns
Xoshiro256+ 0.62 ms 0.62 ns
SplitMix64 0.63 ms 0.63 ns
JSFLarge 0.79 ms 0.79 ns

无运行时依赖