C 多线程如何提供比内核数量更大的加速因子?

C 多线程如何提供比内核数量更大的加速因子?,c,multithreading,C,Multithreading,我将pthreads与gcc一起使用。简单代码示例将线程数“N”作为用户提供的输入。它将一个长数组拆分为N个大小大致相同的子块。每个子块由单独的线程写入 本例中的虚拟处理实际上涉及为每个数组索引休眠固定时间,然后将数字写入该数组位置 代码如下: 然后我从命令行调用它,如下所示: $ time ./a.out 4 当我增加线程数时,我看到速度加快了。对于1个线程,该过程只需10秒多一点。这是有意义的,因为我为每个数组元素睡眠1000 usec,并且有10000个数组元素。接下来,当我转到2个线

我将pthreads与gcc一起使用。简单代码示例将线程数“N”作为用户提供的输入。它将一个长数组拆分为N个大小大致相同的子块。每个子块由单独的线程写入

本例中的虚拟处理实际上涉及为每个数组索引休眠固定时间,然后将数字写入该数组位置

代码如下:

然后我从命令行调用它,如下所示:

$ time ./a.out 4
当我增加线程数时,我看到速度加快了。对于1个线程,该过程只需10秒多一点。这是有意义的,因为我为每个数组元素睡眠1000 usec,并且有10000个数组元素。接下来,当我转到2个线程时,它会下降到5秒多一点,以此类推

我不明白的是,即使我的线程数超过了计算机上的内核数,我也会得到一个加速!我有4个内核,所以我希望>4个线程不会加速。但是,令人惊讶的是,当我跑步时

$ time ./a.out 100

我获得了100倍的加速,处理在~0.1秒内完成!这怎么可能呢?

一些一般背景

一个程序的进度可能会因为很多事情而减慢,但一般来说,您可以将慢点(也称为热点)分为两类:

  • CPU受限:在这种情况下,处理器正在执行一些繁重的数字运算(如三角函数)。如果所有CPU的内核都在执行这些任务,那么其他进程必须等待

  • 内存绑定:在这种情况下,处理器正在等待从硬盘或RAM检索信息。由于它们通常比处理器慢几个数量级,因此从CPU的角度来看,这需要永远的时间

但您也可以想象进程必须等待的其他情况,例如等待网络响应

在许多内存/网络受限的情况下,当内存向CPU爬行时,可以将线程“挂起”,同时执行其他有用的工作。如果这项工作做得很好,那么多线程程序可以很好地执行其单线程等效程序。Node.js使用这种异步编程技术来实现良好的性能

以下是各种延迟的简便描述:

你的问题

现在,回到您的问题:您有多个线程在运行,但它们既不执行CPU密集型工作,也不执行内存密集型工作:没有多少时间需要占用。实际上,sleep函数本质上是告诉操作系统没有做任何工作。在这种情况下,当线程睡眠时,操作系统可以在其他线程中工作。因此,表面性能自然会显著提高


请注意,对于低延迟应用程序,例如MPI,它有时代替睡眠功能。在这种情况下,程序进入一个紧密循环并重复检查一个条件。从外观上看,效果类似,但睡眠不使用CPU,而繁忙等待使用约100%的CPU。

一些一般背景

一个程序的进度可能会因为很多事情而减慢,但一般来说,您可以将慢点(也称为热点)分为两类:

  • CPU受限:在这种情况下,处理器正在执行一些繁重的数字运算(如三角函数)。如果所有CPU的内核都在执行这些任务,那么其他进程必须等待

  • 内存绑定:在这种情况下,处理器正在等待从硬盘或RAM检索信息。由于它们通常比处理器慢几个数量级,因此从CPU的角度来看,这需要永远的时间

但您也可以想象进程必须等待的其他情况,例如等待网络响应

在许多内存/网络受限的情况下,当内存向CPU爬行时,可以将线程“挂起”,同时执行其他有用的工作。如果这项工作做得很好,那么多线程程序可以很好地执行其单线程等效程序。Node.js使用这种异步编程技术来实现良好的性能

以下是各种延迟的简便描述:

你的问题

现在,回到您的问题:您有多个线程在运行,但它们既不执行CPU密集型工作,也不执行内存密集型工作:没有多少时间需要占用。实际上,sleep函数本质上是告诉操作系统没有做任何工作。在这种情况下,当线程睡眠时,操作系统可以在其他线程中工作。因此,表面性能自然会显著提高


请注意,对于低延迟应用程序,例如MPI,它有时代替睡眠功能。在这种情况下,程序进入一个紧密循环并重复检查一个条件。从外部看,效果类似,但睡眠不使用CPU,而繁忙等待使用约100%的CPU。

线程在睡眠时不需要使用CPU。计算机中CPU内核的数量并不限制可以同时睡眠的线程数量。啊!因此,我必须添加一些“真正的”工作(比如一个巨大的循环),而不是我的sleep命令。睡眠不会阻塞CPU@如果您有一个超线程CPU,比如i7,那么即使在使用Uling时,您也可能会得到更快的结果,最多可达8个。@jameslarge您想将您的评论转换为答案吗?在删除sleep命令并添加一个long for循环之后,我现在看到了当线程数>内核数时没有加速的预期结果。这个问题似乎非常熟悉……线程在睡眠时不需要使用CPU。你的机器的CPU核数并不限制可以同时睡眠的线程数。啊
$ time ./a.out 4
$ time ./a.out 100