我有一个四核i7 920 CPU。它是超线程的,因此计算机认为它有8个核心。
从我在interweb上读到的内容来看,在执行并行任务时,我应该使用物理内核的数量,而不是超线程内核的数量。
所以我做了一些时间,并且惊讶地发现在并行循环中使用8个线程比使用4个线程更快。
这是为什么?我的示例代码太长了,无法在此处发布,但可以通过运行以下示例找到:https://github.com/jsphon/MTVectorizer
表现图表如下:
答案 0 :(得分:5)
(英特尔)超线程核心就像(最多)两个CPU。
观察结果是单个CPU拥有一组理想连续繁忙的资源,但实际上在CPU等待某些外部事件(通常是内存读取或写入)时会出现意外情况。
通过为另一个硬件线程添加一些额外的状态信息(例如,寄存器的另一个副本+附加的东西),"单个"当第一个阻塞时,CPU可以将注意力转移到执行另一个线程。 (可以概括这N个硬件线程,其他架构已经做到了这一点;英特尔退出2)。
如果两个硬件线程都花时间等待各种事件,那么CPU可以为硬件线程做相应的处理。内存等待的40纳秒是长时间。因此,如果你的程序获取大量内存,我希望它看起来好像两个硬件线程都是完全有效的,例如,你应该得到近2倍。
如果两个硬件线程正在进行高度本地化的工作(例如,仅在寄存器中进行密集计算),则内部等待变得最小,并且单个CPU无法快速切换以快速为两个硬件线程提供服务因为他们产生了工作。在这种情况下,性能会降低。 我不记得我听到的地方,很久以前我就听说过:在这种情况下,净效应比理想化的2倍更像是1.3倍。 (期待SO观众在此纠正我。)
根据当前正在运行的部分,您的应用程序可能会根据需要来回切换。然后你会得到混合的表现。我对能得到的任何加速感到满意。
答案 1 :(得分: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/)。