6

我有一个四核 i7 920 CPU。它是超线程的,因此计算机认为它有 8 个内核。

根据我在互联网上阅读的内容,在执行并行任务时,我应该使用物理内核的数量,而不是超线程内核的数量。

所以我做了一些计时,很惊讶在并行循环中使用 8 个线程比使用 4 个线程更快。

为什么是这样?我的示例代码太长,无法在此处发布,但可以通过在此处运行示例找到:https ://github.com/jsphon/MTVectorizer

性能图表在这里:

在此处输入图像描述

4

2 回答 2

5

(英特尔)超线程内核就像(最多)两个 CPU。

观察结果是,单个 CPU 拥有一组理想情况下连续忙碌的资源,但实际上在 CPU 等待某些外部事件(通常是内存读取或写入)时经常处于空闲状态。

通过为另一个硬件线程添加一些额外的状态信息(例如,寄存器的另一个副本 + 额外的东西),“单个”CPU 可以在第一个线程阻塞时将注意力转移到执行另一个线程。(可以概括这N个硬件线程,其他架构已经做到了;Intel在2退出)。

如果两个硬件线程都花时间等待各种事件,那么 CPU 可以说可以为硬件线程做相应的处理。40 纳秒的内存等待时间很。因此,如果您的程序获取大量内存,我希望它看起来好像两个硬件线程都完全有效,例如,您应该获得近 2 倍。

如果两个硬件线程正在执行高度本地化的工作(例如,仅在寄存器中进行密集计算),则内部等待将变得最小,并且单个 CPU 无法以足够快的速度切换以像它们生成工作一样快地为两个硬件线程提供服务。在这种情况下,性能会下降。我不记得我在哪里听到的,很久以前就听说过:在这种情况下,净效应更像是 1.3 倍,而不是理想化的 2 倍。(期待 SO 观众对此进行纠正)。

您的应用程序可能会根据当前正在运行的部分来回切换。然后你会得到混合的性能。我对我能得到的任何加速都很满意。

于 2014-11-23T14:04:41.777 回答
1

Ira Baxter 已经很好地解释了您的问题,但我想再补充一件事(无法评论他的答案,因为还没有足够的代表):从一个线程切换到另一个线程会产生开销。此过程称为上下文切换 ( http://wiki.osdev.org/Context_Switching#Hardware_Context_Switching ),至少需要您的 CPU 内核更改其寄存器以反映新线程中的数据。如果您在进行进程级上下文切换,这个成本会很高,但在进行线程级切换时会便宜很多。这意味着两件事:

1) 超线程永远不会给你理论上的 2 倍性能提升,因为上下文切换的成本是不小的。这也是为什么高度逻辑的线程会降低性能的原因,根据 Ira:频繁的上下文切换使成本成倍增加。

2) 8 个单线程进程将比 4 个执行相同工作的双线程进程运行得慢。因此,如果您打算进行多线程工作,您应该使用 Python 的线程库,或者很棒的 greenlet 库 ( https://greenlet.readthedocs.org/en/latest/ )。

于 2014-11-23T16:20:47.363 回答