如何拆分程序以充分利用多CPU,多核和超线程?

时间:2011-01-20 03:49:32

标签: multithreading multicore

我有一堆命令要执行基因分离。 例如:

msclle_program -in 1.txt
msclle_program -in 2.txt
msclle_program -in 3.txt
      .........
msclle_program -in 10.txt

这些命令彼此独立。

环境是Linux桌面,Intel i7( 4核/ 8线程)× 7 12G 内存

我可以将这些命令拆分为不同的n.sh程序并同时运行它们。

我的问题是如何充分利用多CPU,多核和超线程来使程序运行得更快?

更具体地说,我应该拆分多少个程序文件

自己的理解是:

  1. 拆分为7个程序文件。因此每个CPU将100%运行一个程序
  2. 使用一个CPU,CPU将自己利用其多核和多线程。
  3. 是真的吗?

    非常感谢你的评论。

4 个答案:

答案 0 :(得分:6)

答案并不简单或直接,每个CPU将任务分成一个程序可能不是最优的,可能确实很差甚至非常差。

首先,据我所知,你有7个四核CPU(大概有8个,但是你为操作系统保存了一个?)。如果在每个CPU上运行单线程进程,则将在单个核心上使用单个线程。其他三个核心和所有超线程都不会被使用。

硬件和操作系统无法在多个核心上拆分单个线程。

然而,您可以为每个CPU运行四个单线程进程(每个核心一个),甚至八个(每个超线程一个)。这是否最佳取决于过程所做的工作;特别是它们的工作集大小和内存访问模式,以及硬件缓存安排;缓存级别的数量,大小和共享。此外,还需要考虑核心的NUMA安排。

基本上,一个额外的线程必须为你提供相当多的加速,超过它在缓存利用率,主存储器访问和预取中断方面的成本。

此外,由于工作集超过某些缓存限制的效果是深远的,一个或两个核心似乎可能是令人震惊的四或八,所以你甚至不能尝试一个核心并假设结果有用的超过八个。

快速浏览一下,我看到i7有一个小的L2缓存和一个巨大的L3缓存。鉴于您的数据集,如果处理大量数据,我不会感到惊讶。问题是它是否是顺序处理的(例如,如果预取将是有效的)。如果数据没有按顺序处理,您可以通过减少并发进程数来做得更好,因此它们的工作集往往适合L3缓存。我怀疑如果你运行8或16个进程,L3缓存将被敲打 - 溢出。 OTOH,如果您的数据访问是非顺序的,那么L3缓存无论如何都不会为您节省费用。

答案 1 :(得分:1)

您可以生成多个进程,然后将每个进程分配给一个cpu。 您可以使用taskset -c执行此操作。

滚动数字和增量以指定处理器编号。

答案 2 :(得分:1)

  

拆分为7个程序文件。因此每个CPU将100%运行一个程序。

这大致正确:如果你有7个单线程程序和7个处理单元,那么每个程序都有一个线程可以运行。这是最佳的:较少的程序,并且一些处理单元将是空闲的;更多的节目,浪费时间在他们之间交替。虽然,如果你有7个四核处理器,那么最佳线程数(从“CPU绑定角度”)将是28.这是简化的,因为实际上将有其他程序来共享CPU。

  

使用一个CPU,CPU将自己利用其多核和多线程。

没有。所有核心是否都在单CPU中并没有什么区别(尽管它在缓存方面确实有所不同)。无论如何,处理器不会自己进行任何多线程处理。这是程序员的工作。这就是为什么现在让程序变得更快变得非常具有挑战性:直到大约2005年左右,随着时钟频率稳步上升,这是免费乘车,但现在已达到极限,加速程序需要将它们分成越来越多的处理单位。这是函数式编程复兴的主要原因之一。

答案 3 :(得分:0)

为什么将它们作为单独的进程运行?考虑在一个进程中运行多个线程,这样可以使内存占用空间更小,并降低所需的进程调度量。

你可以这样看待它(有点过于简化但仍然):

考虑将您的工作分为可处理单元(PU)。然后,您需要两个或多个核心,每次处理一个PU,这样它们不会相互干扰,核心越多,您可以处理的PU越多。

处理一个PU所涉及的工作是输入+处理+输出(I + P + O)。由于它可能是来自大型存储器结构的处理单元,其中包含数百万或更多的输入和输出主要与存储器有关。使用一个核心这不是问题,因为没有其他核心干扰内存访问。对于多个核心,问题基本上移动到最近的公共资源,在这种情况下,L3缓存提供缓存输入(CI)和缓存输出(CO)。对于两个内核,您希望CI + CO等于或小于P / 2,因为这两个内核可以轮流访问最近的公共资源(L3缓存)而不会相互干扰。有三个核心CI + CO需要P / 3和四个或八个核心,你需要CI + CO等于P / 4或P / 8。

因此,诀窍是使PU所需的处理完全驻留在核心及其自身的缓存(L1和L2)中。您拥有的核心越多,PU应该越大(与所需的I / O相关),这样PU就会尽可能长时间地隔离在其核心内,并且需要在其本地缓存中提供所需的所有数据。

总结一下,您希望内核尽可能多地进行有意义且高效的处理,同时尽可能少地影响L3缓存,因为L3缓存是瓶颈。实现这种平衡是一项挑战,但绝不是不可能的。

正如您所理解的那样,执行“传统”多线程管理或Web应用程序的核心(无需任何关心以节省L3访问)将不断相互冲突,以便进一步访问L3缓存和资源。在多个内核上运行的多线程程序比在单核上运行的程序要慢,这种情况并不少见。

另外,不要忘记操作系统工作也会影响缓存(很多)。如果你把问题分成不同的过程(正如我上面提到的那样),你将在操作系统中调用比绝对必要的更多的裁判。

我的经验是,问题的存在,应有和不应该是未知或不理解的。