在同步代码中使用async/await是否有性能优势?

huangapple go评论62阅读模式
英文:

Is there any performance advantage to use async/await amid synchronous code?

问题

我试图理解何时使用异步以及何时可以提高性能。

我知道它在替代阻塞IO操作,如文件IO、HTTP调用、数据库操作等方面非常强大,但我想知道在性能方面是否还有其他方面的考虑。

一个具体的例子可能是大内存复制(移动大向量或复制大量数据等)。这是一个同步操作,就程序的其余部分而言可能需要一些时间。这个例子是否可以利用异步/await 来在等待复制时执行其他操作,还是线程必须等待内存复制完成才能继续执行?

如果不是这个直接的例子,也许还有其他同步操作可以通过异步/await 来提高性能?

英文:

Im trying to understand when to use async and when it can improve performance.

I know it’s most-powerful in replacing otherwise-blocking IO operations like file IO, http calls, database operations, etc., but I was wondering if there’s any point beyond that (at least as far as performance is concerned).

A specific example might be large memory copies (shifting a large vector or otherwise copying lots of data). This is a synchronous operation that might take a while as far as the rest of the program is concerned. Can this example take advantage of async/await in order to do other things while we wait for the copy, or must the thread wait for the memory copy before it continues to execute?

If not this direct example, maybe another synch operation that can be improved via async/await?

答案1

得分: 5

Async/await不会提供任何并行性,只有并发性。这意味着使用async/await来划分工作的同步操作只会依次运行,速度不会比没有async/await更快,实际上会因为增加了开销而变慢。

你只能通过线程来实现并行性,并且受到系统中可用核心数量的限制。

一些异步运行时确实会使用多个线程并行运行代码,因此如果你使用得当,你将获得一些并行性(因此速度会更快);但这只会增加使用线程直接或使用诸如rayon这样避免async/await并且仅使用线程并行化代码的库的开销。

如果你不受I/O限制,不要使用async/await。你将无法获益。

英文:

Async/await does not give you any parallelism, only concurrency. That means that any sync operation using async/await to divide the work will just run one part after the other, not faster than without async/await and in fact slower because it adds overhead.

You can only get parallelism via threads, and you are limited to the number of cores you have in your system.

Some async runtimes do run the code in parallel, using multiple threads, so you will get some parallelism (and therefore speed) if you'll use them correctly; but this just adds overhead over using threads directly, or using a library such as rayon that avoids async/await and parallelizes the code using threads only.

If you're not I/O bound, don't use async/await. You have nothing to gain.

答案2

得分: 3

理论上是的。

在CppCon 2015上,Gor Nishanov介绍了他在C++中实验性协程实现方面的工作:C++协程 - 一个负担不重的抽象。C++协程在某种程度上与Rust的async/await有所不同(甚至在实现上也不同),但这里的区别并不重要。

演讲的重点是,通过利用内存预取,某些算法可以加速使用协程。从代码的角度来看,内存访问通常是同步的,但在CPU级别实际上是异步的。然后,关键是:

  • 触发预取操作。
  • 暂停执行 - 并做其他事情。
  • 恢复执行,此时预取的内存应该位于L1,立即可用。

现在,值得注意的是,协程(或async/await)实际上不是特别“必要”来实现这种效果...它们只是一种抽象,毕竟。然而,抽象允许以更简洁/富有表现力的方式表达这一点。

因此,在实际应用中,一些所谓的“同步”算法可能通过使用async/await来进行优化,从而利用CPU的异步操作。

英文:

In theory, yes.

At CppCon 2015, Gor Nishanov presented his work on an experimental coroutine implementation for C++: C++ coroutines - a negative overhead abstraction. C++ coroutines are somewhat different (even implementation-wise) then Rust async/await, but the difference doesn't matter here.

The key highlight of the talk was that certain algorithms could get a speed up from using coroutines by exploiting memory pre-fetching. While from the point of view of the code, a memory access is typically synchronous, it is actually asynchronous at the CPU level. The trick, then, is to:

  • Trigger the pre-fetch.
  • Suspend execution -- and do something else.
  • Resume execution, at which point the pre-fetched memory should be in L1, immediately available.

Now, it is notable that a coroutine (or async/await) isn't particularly needed to achieve this effect... they are just an abstraction, after all. Still, abstractions allow expressing that in a much more succinct/expressive ways.

So, in practice, a number of so-called "synchronous" algorithms could potentially be optimized with async/await, exploiting CPU asynchronous operations.

huangapple
  • 本文由 发表于 2023年6月15日 19:19:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76481940.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定