Can rust async run in parallel?

I learned that async run lazily as it only run when the thread is idle. But is it possible for async to spawn thread and run parallel if the server has multi core cpu ?

Where did you learn this? This is false.

Not sure what do you mean by this, but I'll give it a try nonetheless:

Async is for IO-heavy tasks, not for CPU-intensive tasks. If you want something to run in parallel, don't use async. In Rust, async runtimes such as Tokio provide specific APIs and a threadpool for running CPU-intensive tasks, precisely so that these don't block the threads dedicated for running the async tasks.

1 Like

Probably better to think about Rust async as the language feature, which simply allows incremental progress on some code, and async executors, like tokio, separately.

For an executor to be able to run a Future on multiple threads requires that the Future and it's Output implement Send, which means it can (roughly) be sent to another thread safely. For example, see the where bounds on Tokio spawn()

The thing that determines whether the Future returned from your async code implements Send is essentially whether you hold anything that isn't Send across an .await, for example a mutex lock.

Futures that aren't Send safe often called local futures, so the equivalent single thread API is often named that, for example Tokio's LocalSet allows handling multiple local futures on the same thread safely.

2 Likes

This is my understanding of async, parallel, and what we have in Rust (my usage of certain terms may not be super accurate -- e.g. what's a "task").

Imagine a restaurant, where you have employees preparing meals.

  1. An employee can make one meal, put it in the oven, wait till it's done, then give it to the customer.
  2. The employee can then make another meal. This is serial execution.
  3. To save time, the employee, while meal 1 is in the oven, can go and work on meal 2.
  4. This is what we call async.
  5. Making a meal comprises of many parts, some may need your attention (e.g. using a knife), others may not (e.g. wait for food blender / oven).
  6. While steps continue to require an employee's attention, their attention is always on one meal.
  7. When they encounter a step that they have to wait, they can switch their attention to another meal. These are the .await points.
  8. In Rust, a task is (usually) a series of CPU steps, until the code runs some IO.
  9. Parallelism is when you have more than one employees making more than one meal.
  10. A Future is Send if different employees can work on the same meal -- i.e. employee A put meal 1 in the oven, but employee B took it out and delivered it.
  11. If a Future is not Send, then the same employee has to come back and continue making the meal.
  12. tokio is one such "restaurant", and the current-thread flavour runs with one employee, and the multi-thread flavour runs with multiple employees.
  13. tokio::task::spawn is like an employee sending a special order to dedicated employees who prepare meals that need full attention for extended periods of time.
  14. That's because if you take away a front line employee's attention for too long, the orders pile up.

someone else can probably continue this :smile:

2 Likes

I think your point 13 is supposed to be spawn_blocking or something? Otherwise I'm not sure I understand what the metaphor is trying to say - spawn is the standard API to "start an order"