最大线程数和多线程

5
我对多线程的概念有些不太理解。
例如,我的处理器有2个核心(并且具有超线程),每个核心有2个线程,总共有4个线程。这是否意味着我的CPU可以同时执行四个独立的指令?每个线程都能成为多线程吗?

2
一个单核心就可以同时执行多个指令。四个核心可以同时执行四个不同的线程。 - Hans Passant
2个回答

6
那么这是否意味着我的CPU可以同时执行四个不同的指令?每个线程是否能够是多线程?
简而言之,是的。
由于某些因素,如流水线等,CPU每个时钟周期只能执行1个单独的指令,但由于流水线,CPU可能能够在单个时钟周期内通过不同阶段传递多个指令,并且时钟频率可能非常快,但仍然只有1条指令。
例如,NOP是x86汇编指令,CPU将其解释为“本周期不进行操作”,这是从甚至简单如以下代码中执行的数百或数千条(及更多)指令之一:
int main(void)
{
    while (1) { /* eat CPU */ }
    return 0;
}

一个 CPU 执行线程 是指正在执行一系列指令(指令线程),不管这些指令来自哪个应用程序,CPU 都不知道高级概念(如应用程序),这是操作系统的功能。
因此,如果你有一台具有 2(或 4/8/128 等)个共享相同内存(缓存/RAM)的 CPU 的计算机,则可以拥有 2(或多个)个 CPU 可以在(字面上)完全相同的时间运行 2(或多个)个指令。请记住,这些是同时运行的机器指令(即软件的物理方面)。
一个 操作系统级线程 有点不同。虽然 CPU 处理执行的物理方面,但操作系统处理逻辑方面。上述代码分解为多个指令,并且在执行时,在多个 CPU 上实际运行(在多 CPU 感知的环境中),即使它是单个 "线程"(在操作系统级别),操作系统也会安排何时运行下一个指令以及在哪个 CPU 上运行(基于操作系统的线程调度策略,在各种操作系统之间是不同的)。因此,上述代码将占用该 CPU 上给定 "时间片段" 的 100% CPU 使用率。
这种 "时间" 的 "切片"(也称为抢占式计算)是操作系统可以同时运行多个应用程序的原因,它并不是字面上的同一时间,因为 CPU 一次只能处理 1 条指令,但对于一个人来说(谁几乎无法理解 1 秒钟的长度),它似乎是 "同时的"。
当运行应用程序时,内核(操作系统)实际上会生成一个单独的线程(内核线程)来运行该应用程序,此外,该应用程序可以请求创建另一个外部线程(即生成另一个进程或分叉),或通过调用操作系统的(或编程语言的)API 创建一个内部线程,其实际上调用较低级别的内核例程来生成和维护生成的线程的上下文切换,此外,任何已创建的线程也可以调用相同的 API 来生成其他单独的线程(因此,线程能够是 "多线程的")。
多线程(在应用程序和操作系统的意义上)并不一定可移植,因此,虽然您可能学习Java或C#并使用它们的API(即Thread.StartRunnable),但实际使用操作系统提供的API(即CreateThreadpthread_create和大量其他并发函数)会为设计决策打开不同的门(例如:“平台X是否支持线程库Y”),这是需要牢记的一点,当您探索不同的API时。
我希望这能帮助增加一些清晰度。

关于API和应用程序级别的多线程,需要注意的另一个关键点是,每个操作系统(以及单独的编程线程库)通常以不同的方式实现线程(尽管有尝试创建可移植的线程选择)。因此,为一个操作系统编写多线程代码并不能保证它可以在另一个操作系统上移植。总之,你的回答提供了很好的概述和努力。 - David C. Rankin
哇,太棒了txtechhelp的回复。这解决了所有问题。我不知道有“操作系统级线程”的存在。我在哪里可以学习更多关于线程的知识? - collinskewl2
@collinskewl2,我已经编辑了我的答案,但是“操作系统级别”表示在更高(逻辑)层面上,而不是硬件本身(即CPU)。我还放了一些不同的线程API链接,让您可以更好地掌握它,同时拿起您喜欢的编译器并试一试 :) - txtechhelp
@DavidC.Rankin,谢谢!我原本打算为了简洁起见省略可移植性的部分,但在OP发帖要求更多信息(以及您的评论)后,我意识到我不应该牺牲这种简洁性 :) - txtechhelp
1
第二段是误导性的,所有现代流水线处理器都可以在单个CPU核心的一个时钟周期内执行多个指令。例如,对于英特尔或AMD的高端现代台式机芯片(Core i7或Ryzen),它可能在每个时钟周期内完成约10条指令。这是实现的多种方式之一,其中几个主要方式是:(i)具有多个算术单元,(ii)流水线处理:将每个指令的工作分成较小的块,以便多个连续指令的小块工作可以同时完成。 - Rob Wilton
@RobWilton 我试图强调“一次一个”的重点,而不会降低太多级别,但完全同意这可能会被误解。我重新措辞以增加清晰度。感谢你的指出! - txtechhelp

0

我在操作系统课程中研究过这个话题。

使用线程时,对于CPU绑定的进程,一个很好的经验法则是使用与核心数相同的线程,除非是超线程系统,在这种情况下应该使用两倍于核心数量的线程。另一个可以得出的经验法则是针对I/O绑定的进程。这个规则是将线程数乘以每个核心四倍,但对于超线程系统,则可以将线程数乘以每个核心四倍。


这个规则是将每个核心的线程数量增加四倍,除了超线程系统的情况下,可以将每个核心的线程数量增加四倍。这两种情况听起来很相似。除此之外,这是一个简短而好的回答! - Am_I_Helpful
视频编码器libx264默认启动N=1.5倍的逻辑CPU线程数。由于计算中存在依赖关系,因此它具有复杂的工作分派方式,因此可以使用更简单的分派逻辑,并让操作系统负责运行可运行的线程。在更简单的情况下,对于CPU绑定的工作线程,每个逻辑核心一个线程是明智的选择。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接