#thread #parallel #performance #no-std

no-std fast-steal

特别快的多线程库,支持超细颗粒度的任务窃取

19 stable releases (3 major)

Uses new Rust 2024

new 3.0.3 May 3, 2025
3.0.2 Apr 26, 2025
2.6.0 Apr 20, 2025
1.2.1 Apr 5, 2025
0.1.2 Apr 3, 2025

#232 in Concurrency

Download history 573/week @ 2025-04-02 1050/week @ 2025-04-09 418/week @ 2025-04-16 370/week @ 2025-04-23

2,411 downloads per month
Used in 2 crates (via fast-down)

MIT license

33KB
679 lines

fast-steal 神偷

GitHub last commit (branch) Rust Latest version Documentation License

fast-steal 是一个特别快的多线程库,支持超细颗粒度的任务窃取。

优势

  1. no_std 支持,不依赖于标准库
  2. 零拷贝
  3. 安全的 Rust 代码
  4. 超细颗粒度任务窃取,速度非常快
use fast_steal::{Spawn, TaskList, action};
use std::{
    collections::{HashMap, hash_map::Entry},
    sync::{Arc, mpsc},
    thread,
};

fn fib(n: usize) -> usize {
    match n {
        0 => 0,
        1 => 1,
        _ => fib(n - 1) + fib(n - 2),
    }
}

fn fib_fast(n: usize) -> usize {
    let mut a = 0;
    let mut b = 1;
    for _ in 0..n {
        (a, b) = (b, a + b);
    }
    a
}

fn main() {
    let tasks: Arc<TaskList> = Arc::new(vec![0..48].into());
    let (tx, rx) = mpsc::channel();
    let tasks_clone = tasks.clone();
    let handles = tasks.clone().spawn(
        8,
        |executor| thread::spawn(move || executor.run()),
        action::from_fn(move |id, task, refresh| { // use `action::from_fn` for type inference
            loop {
                // 必须在每次循环开始判断 task.start() < task.end(),因为其他线程可能会修改 task
                while task.start() < task.end() {
                    let i = tasks_clone.get(task.start());
                    // 提前更新进度,防止其他线程重复计算
                    task.fetch_add_start(1);
                    // 计算
                    tx.send((i, fib(i))).unwrap();
                }
                // 检查是否还有任务
                if !refresh() {
                    break;
                }
            }
        }),
    );
    // 汇总任务结果
    let mut data = HashMap::new();
    for (i, res) in rx {
        // 如果重复计算就报错
        match data.entry(i) {
            Entry::Occupied(_) => {
                panic!("数字 {i},值为 {res} 重复计算")
            }
            Entry::Vacant(entry) => {
                entry.insert(res);
            }
        }
        data.insert(i, res);
    }
    // 等待任务结束
    for handle in handles {
        handle.join().unwrap();
    }
    // 验证结果
    dbg!(&data);
    for i in 0..tasks.len {
        let index = tasks.get(i);
        assert_eq!((index, data.get(&index)), (index, Some(&fib_fast(index))));
    }
}

Dependencies

~400KB