#integer #set #bounded #performance #random-access #delphic

bin+lib fastset

密集、有界整数集合的快速实现,针对快速更新和访问进行优化

8 个不稳定版本 (3 个破坏性更新)

0.4.1 2024 年 4 月 5 日
0.4.0 2024 年 4 月 1 日
0.3.0 2024 年 3 月 23 日
0.2.1 2024 年 3 月 21 日
0.1.2 2024 年 3 月 13 日

#310数据结构

每月 35 次下载
用于 signvec

MIT 许可证

125KB
2K SLoC

fastset

Crates.io docs.rs License GitHub Workflow Status

密集、有界整数集合的快速实现,提供快速更新和随机访问。

特性

  • 针对无符号整数(usize)元素定制,非常适合基于索引的应用
  • 快速插入、删除和成员检查
  • 使用 random 方法进行均匀随机抽样
  • 分页机制以在一定程度上减轻大内存占用[^1]

请注意,虽然分页改善了现有的内存占用,但 fastset::Set 仍然 不是内存受限应用程序或需要存储稀疏元素的存储应用程序的好解决方案。对于页大小的两倍稀疏的整数,具有分页功能的 fastset::Set 的峰值堆分配约为 std::collections::HashSet 的 8 倍。

[^1]: 在 0.4.0 中引入了分页机制,减少了 fastset::Set 的内存占用。具有分页功能后,fastset::Set 在没有额外性能开销的情况下,峰值堆内存分配减少了约 50%。

基准测试

操作 fastset::集合 hashbrown::HashSet std::collections::HashSet
插入 1.1632 纳秒 4.7105 纳秒 14.136 纳秒
删除 1.1647 纳秒 3.0459 纳秒 10.625 纳秒
包含 932.81 皮秒 985.38 皮秒 13.827 纳秒
随机 651.26 皮秒 N/A N/A
  • CPU: AMD Ryzen™ 5 5600G with Radeon™ Graphics x 12
  • RAM: 58.8 GiB
  • OS: Guix System, 64-bit

用法

use fastset::{set, Set};
use nanorand::WyRand;

   let mut set = set![5, 10, 15, 20, 25, 30]; // Initialize set with elements
   assert!(set.contains(&5)); // Check for element presence

   set.insert(35); // Insert a new element
   assert!(set.contains(&35));

   set.remove(&5); // Remove an element
   assert!(!set.contains(&5));

   if let Some(taken) = set.take(&10) { // Remove and return an element
       assert_eq!(taken, 10);
   }

   let mut rng = WyRand::new();
   if let Some(element) = set.random(&mut rng) { // Get a random element
       set.remove(&element); // Remove the randomly selected element
       assert!(!set.contains(&element));
   }

   println!("Set: {:?}, Length: {}", set, set.len()); // Display the set and its length

Delphic 集合

fastset::Set,在此实现中,满足德尔菲集[1]、[2]的条件。

设Ω为一个离散宇宙。一个集合(S ⊆ Ω)如果能在O(log |Ω|)时间内支持以下操作,则被视为德尔菲家族的成员:

  • 成员资格:验证是否存在元素(x ∈ Ω)属于(S)。
  • 基数:确定(S)的大小,即(|S|)。
  • 抽样:从(S)中抽取一个均匀随机样本。

src/set.rs中的单元测试使用基本的卡方检验验证了均匀抽样的属性。

use fastset::Set;
use nanorand::WyRand;
use statrs::distribution::{ChiSquared, ContinuousCDF};

fn sampling_is_uniformly_at_random() {
    const SAMPLES: usize = 1_000_000;
    const EDGE_OF_THE_UNIVERSE: usize = 10000;

    let elements = (1..=EDGE_OF_THE_UNIVERSE).collect::<Vec<_>>();
    let set = Set::from(elements.clone());
    let mut rng = WyRand::new_seed(42u64);
    let mut counts = vec![0f64; elements.len()];

(0..SAMPLES).for_each(|_| {
   if let Some(value) = set.random(&mut rng) {
       counts[value - 1] += 1.0;
   }
});

    let e = SAMPLES as f64 / elements.len() as f64;
    let statistic: f64 = counts.iter().map(|&o| { (o - e) * (o - e) / e }).sum();

    let dof = elements.len() - 1;
    let chi = ChiSquared::new(dof as f64).unwrap();
    let acceptable = chi.inverse_cdf(0.99);

    // Null hypothesis: Elements are sampled uniformly at random
    assert!(
        statistic < acceptable,
        "Chi-square statistic {} is greater than what's acceptable ({})",
        statistic,
        acceptable,
    );
}

参考文献

[1]: Chakraborty, Sourav, N. V. Vinodchandran, and Kuldeep S. Meel. "Distinct Elements in Streams: An Algorithm for the (Text) Book." arXiv预印本 arXiv:2301.10191 (2023).

[2]: Meel, Kuldeep S., Sourav Chakraborty, and N. V. Vinodchandran. "Estimation of the Size of Union of Delphic Sets: Achieving Independence from Stream Size." 第41届ACM SIGMOD-SIGACT-SIGAI数据库系统原理研讨会论文集。2022。

依赖关系

~0.4–1MB
~23K SLoC