15

If you're spawning multiple threads (or processes) concurrently, is it better to spawn as many as the number of physical processors or the number of logical processors, assuming the task is CPU-bound? Or is it better to do something in between (say, 3 threads)?

Does the performance depend on the kind of instructions that are getting executed (say, would non-local memory access be much different from cache hits)? If so, in which cases is it better to take advantage of hyperthreading?


Update:

The reason I'm asking is, I remember reading somewhere that if you have as many tasks as the number of virtual processors, tasks on the same physical core can sometimes starve some CPU resources and prevent each other from getting as many resources as needed, possibly decreasing performance. That's why I'm wondering if having as many threads as virtual cores is a good idea.

4

6 回答 6

5

The performance depends on a huge variety of factors. Most tasks are not strictly CPU bound, since even if all of the data is in memory it is usually not on-board in the processor cache. I have seen examples (like this one) where memory access patterns can dramatically change the performance profile of a given 'parallel' process.

In short, there is no perfect number for all situations.

于 2011-01-22T23:13:58.087 回答
4

在启用超线程的情况下,您很有可能会看到每个内核运行 2 个线程的性能改进。看起来完全受 CPU 限制的作业通常不是,超线程可以从偶尔的中断或上下文切换中提取一些“额外”周期。

另一方面,使用具有 Turbo Boost 的 core iX 处理器,实际上每个内核运行 1 个线程可能会更好,以鼓励 CPU 自行超频。

在工作中,我们经常以全 CPU 运行多核服务器,一次进行数天的各种计算。不久前,我们测量了使用和不使用 HT 的性能差异。我们发现,平均而言,使用超线程,并且一次运行两倍的作业,我们可以比不使用超线程快 10% 左右完成相同数量的作业。

假设 2 × 内核是一个很好的起点,但底线是:测量!

于 2011-01-22T23:44:24.310 回答
2

I remember info that hyperthreading can give you up to 30% of performance boost. in general you'd better to treat them as 4 different cores. of course in some specific circumstances (e.g. having the same long running task bound to each core) you can divide your processing better taking into account that some cores are just logical ones

more info about hyperthreading itself here

于 2011-01-22T23:09:49.657 回答
2

使用超线程在同一个内核上运行两个线程,当两个线程具有相似的内存访问模式但访问不相交的数据结构时,将非常大致相当于在两个单独的内核上运行它们,每个内核都有一半的缓存。如果内存访问模式的一半缓存足以防止抖动,则性能可能会很好。如果内存访问模式使得将缓存减半会导致抖动,那么性能可能会下降 10 倍(这意味着如果没有超线程,性能会好得多)。

另一方面,在某些情况下,超线程可能是一个巨大的胜利。如果许多线程都将使用无锁数据结构读取和写入相同的共享数据,并且所有线程都必须看到一致的数据视图,那么尝试在不相交的处理器上运行线程可能会导致抖动,因为一次只有一个处理器可能对任何给定的高速缓存行具有读写访问权限;在两个核心上运行这样的线程可能比一次只运行一个需要更长的时间。但是,当单个内核上的多个线程访问一条数据时,不需要这种缓存仲裁。在这些情况下,超线程可能是一个巨大的胜利。

不幸的是,我不知道有什么方法可以给调度程序任何“提示”来建议一些线程应该尽可能共享一个核心,而其他线程应该尽可能单独运行。

于 2012-01-18T20:27:47.737 回答
1

对于使用额外虚拟内核的大多数CPU 密集型任务,HT 允许大约 10-30% 的提升。尽管这些任务可能看起来受 CPU 限制,但除非它们是定制的程序集,否则它们通常会遭受 RAM 和本地缓存之间的 IO 等待。这允许一个线程在启用了物理 HT 的核心上运行,而另一个线程正在等待 IO。但是,这确实有一个缺点,因为两个线程共享相同的缓存/总线,这将导致每个资源更少,这可能导致两个线程在等待 IO 时暂停。

在最后一种情况下,运行单线程将降低最大同时理论处理能力(降低 10-30%),有利于运行单线程而不会减慢缓存抖动,这在某些应用程序中可能非常重要。

选择使用哪些内核与选择运行多少线程一样重要。如果每个线程在大致相同的持续时间内受 CPU 限制,最好设置亲和性,以便使用大部分不同资源的线程发现自己位于不同的物理核心上,而使用公共资源的线程被分组到相同的物理核心(不同的虚拟核心),所以可以从同一个缓存中使用公共资源,而无需额外的 IO 等待。

由于每个程序都有不同的 CPU 使用特性,并且缓存抖动可能会或可能不会是主要的减速(通常是),因此如果不首先进行分析,就不可能确定理想的线程数应该是多少。最后要注意的一件事是操作系统/内核还需要一些 CPU 和缓存空间。如果 CPU 绑定线程需要实时延迟以避免共享缓存/cpu 资源,通常为操作系统保留一个(物理)内核是理想的。如果线程经常等待 IO 并且缓存抖动不是问题,或者如果运行专门为应用程序设计的实时操作系统,则可以跳过最后一步。

http://en.wikipedia.org/wiki/Thrashing_(computer_science) http://en.wikipedia.org/wiki/Processor_affinity

于 2013-12-12T15:14:40.293 回答
0

所有其他答案已经提供了很多很好的信息。但是,需要考虑的另一点是 SIMD 单元在同一裸片上的逻辑内核之间共享。那么,如果您使用 SSE 代码运行线程,您是在所有 4 个逻辑内核上运行它们,还是只生成 2 个线程(假设您有两个芯片)?对于这种奇怪的情况,最好使用您的应用程序进行分析。

于 2012-01-18T20:36:48.360 回答