【问题标题】:Rust : futures::future::join_all(...).await runs futures sequentially but parallelism wantedRust:futures::future::join_all(...).await 顺序运行期货,但需要并行性
【发布时间】:2021-11-04 03:06:55
【问题描述】:

我有以下async函数(实现不重要):

async fn long_task(task_number: i32) {
    // do some long work
    println!("Task {} executed", task_number);
}

我想同时运行这个函数n次,所以我定义了这个函数:

async fn execute_long_tasks_async(n: i32) {
    let mut futures = Vec::new();
    for i in 1..=n {
        futures.push(long_task(i));
    }
    futures::future::join_all(futures).await;
}

我正在使用join_all 函数等待所有任务执行完毕。然后我在main 中调用这个函数:

fn main() {
    futures::executor::block_on(execute_long_tasks_async(3));
}

我的问题是任务是按顺序运行的:

Executing task 1
Task 1 executed
Executing task 2
Task 2 executed
Executing task 3
Task 3 executed

但我希望它同时运行,我会得到类似的东西:

Executing task 1
Executing task 3
Executing task 2
Task 1 executed
Task 3 executed
Task 2 executed

是否有替代futures::future::join_all 来并行运行所有任务?

我想使用await 创建一个简单的示例来演示asyncawait

【问题讨论】:

  • “我有以下异步函数(实现不重要):” - 实现很重要。 AFAIK,block_on 使用单线程执行。 Future 一直运行,直到它在某个 .await 上被阻止或直到它到达终点。如果您的async fn 中没有.await-s,则它永远不会产生,并且在完成之前不允许其他期货执行。

标签: asynchronous rust async-await


【解决方案1】:

join_all 并发运行任务(非并行)。它的局限性在于它只能在任务屈服时在任务之间切换。此外,如果第一个任务还没有准备好,它总是喜欢处理第一个任务。

如果您的功能是例如定义为

async fn long_task(task_number: i32) {
    println!("Executing Task {}", task_number);
    tokio::time::delay_for(Duration::from_secs(1)).await;
    println!("Task {} executed", task_number);
}

那么函数中间的await/suspend 点将为join_all 提供运行其他函数的机会/Futures - 您将观察到预期的输出。

但是,如果long_task 没有产生(例如因为它会是线程阻塞),那么这个函数将在其他任务开始之前运行完成:

async fn long_task(task_number: i32) {
    println!("Executing Task {}", task_number);
    std::thread::sleep(Duration::from_secs(1));
    println!("Task {} executed", task_number);
}

如果您有这样的功能,它们通常不适合async 世界。 async 函数的设计目的不是 CPU 密集型,并且不应阻塞线程 - 以便在同一执行器上调度的其他函数仍然可以运行。

一种可能为您提供更多并行性的替代方法是使用多线程异步运行时(例如 tokio)和 spawn 每个异步函数作为单独的任务。在这种情况下,任务可以在单独的 CPU 内核和线程上运行,并且不会相互阻塞。然后您可以在返回的JoinHandles 集合上使用join_all 等待所有任务完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-25
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 2021-01-27
    相关资源
    最近更新 更多