Выполняются ли два .awaits (в одном блоке или функции asyn c) параллельно? - PullRequest
0 голосов
/ 04 апреля 2020

Я пытался изучить async / await и придумал простой код ниже:

const N: usize = 100000;

fn main() {
    println!("Hello, world!");


    let mut my_array = [0u32; N];
    let mut my_vector = Vec::new();

    for i in 0..my_array.len() {
        my_array[i] = i as u32;
    }

    for i in 0..N {
        my_vector.push((i * i) as u32);
    }

    let mut array_sum = 0;
    let mut vector_sum = 0;

    async_std::task::block_on(
        async {
            array_sum = sum_slice(&my_array).await;
            vector_sum = sum_slice(&my_vector).await;

            println!("Sum of array = {}", array_sum);
            println!("Sum of vector = {}", vector_sum);
        }
    );

println!("Total sum = {}", array_sum + vector_sum);

}

async fn sum_slice(slice: &[u32]) -> u64 {
    println!("Summing...{} to {}", slice.first().unwrap(), slice.last().unwrap());
    slice.iter().fold(0, |a, &b| a + b as u64) 
}

В этом коде два вызова функции sum_slice() действительно выполняются асинхронно в двух разных потоках и параллельно?

Я спрашиваю это, потому что строка:

println!("Summing...{} to {}", slice.first().unwrap(), slice.last().unwrap());

всегда сначала печатает массив, например:

Summing...0 to 99999
Summing...0 to 1409865409

РЕДАКТИРОВАТЬ: изменил код таким образом ... какой из путей между (1) и (2) предпочтительнее?

use futures::join;

const N: usize = 10000;

#[async_std::main]
async fn main() {

    let mut my_array = [0u32; N];
    let mut my_vector = Vec::new();

    for i in 0..my_array.len() {
        my_array[i] = i as u32;
    }

    for i in 0..N {
        my_vector.push((i * i) as u32);
    }

    //(1) st way
    let array_sum = sum_slice(&my_array).await;
    let vector_sum = sum_slice(&my_vector).await;

    println!("Sum of array = {}", array_sum);
    println!("Sum of vector = {}", vector_sum);
    println!("Total sum = {}", array_sum + vector_sum);

    //(2) nd way
    async_std::task::block_on(
        async {
            let (array_sum, vector_sum) = join!(sum_slice(&my_array), sum_slice(&my_vector));

            println!("Sum of array = {}", array_sum);
            println!("Sum of vector = {}", vector_sum);
            println!("Total sum = {}", array_sum + vector_sum);
        });
}

async fn sum_slice(slice: &[u32]) -> u64 {
    println!("Summing...{} to {}", slice.first().unwrap(), slice.last().unwrap());
    slice.iter().fold(0, |a, &b| a + b as u64)   
}

Спасибо за любую помощь.

РЕДАКТИРОВАТЬ 2:

Если Я пытаюсь запустить этот код в контексте выше, я получаю pani c:

use futures::join;
use std::sync::Arc;    

const N: usize = 10000;

#[async_std::main]
async fn main() {

    let mut my_array = [0u32; N];
    let mut my_vector = Vec::new();

    for i in 0..my_array.len() {
        my_array[i] = i as u32;
    }

    for i in 0..N {
        my_vector.push((i * i) as u32);
    }  

    let a_arc = Arc::new(my_array);
    let v_arc = Arc::new(my_vector);

    let arr = a_arc.clone();
    let vec = v_arc.clone();

    println!("Try 0:");
    async_std::task::spawn(
          async move {            
             let future1 = sum_slice(&*arr);
             let future2 = sum_slice(&*vec);

              let (array_sum, vector_sum) = join!(future1, future2);

              println!("Sum of array = {}", array_sum);
              println!("Sum of vector = {}", vector_sum);
              println!("Total sum = {}", array_sum + vector_sum);
       });
}

async fn sum_slice(slice: &[u32]) -> u64 {
    println!("Summing...{} to {}", slice.first().unwrap(), slice.last().unwrap());
    slice.iter().fold(0, |a, &b| a + b as u64)  
}

Я получаю следующую ошибку:

Try 0:
thread 'async-std/executor' panicked at 'cannot access stdout during shutdown', src\libstd\io\stdio.rs:487:25
stack backtrace:

Может кто-то указать ошибку я делаю, пожалуйста? Моя цель - запустить две задачи sum_slices () как asyn c друг друга и главного.

Спасибо.

ОБНОВЛЕНИЕ:

Думаю, я наконец-то понял это out.

    const N: usize = 10000;        

   fn main() {
        let mut my_array = [0u32; N];
        let mut my_vector = Vec::new();

        for i in 0..my_array.len() {
            my_array[i] = i as u32;
        }

        for i in 0..N {
            my_vector.push((i * i) as u32);
        }

        let task2 = task::spawn(async move {
            let res = sum_slice(&my_array).await;
            println!("done....task 2");
            res
        });

        let task3 = task::spawn(async move {
            let res = sum_slice(&my_vector).await;
            println!("done....task 3");
            res
        });

        task::block_on(async {
            println!("waiting for the tasks...");

            let res2 = task2.await;
            let res3 = task3.await;

            println!("task2 and task3 ended with result {}", res2+res3);
        }
}

Теперь все вычисляется асин c друг с другом:

waiting for the tasks...
Summing...0 to 9999
Summing...0 to 99980001
done....task 2
done....task 3

task2 and task3 ended with result 333333330000
...