我有一大堆要运行的作业(数千个),每个作业在一个CPU上需要30分钟到几个小时。内存要求很小(每个KB很少)。我正在开发一个拥有几十个CPU的小型Linux集群。到目前为止,我一直在开始运行它们,尝试手动保持群集忙。
我的问题是:如果我一次提交数百或数千,会发生什么 - 远远超过CPU的数量?很明显,每个作业需要更长的时间来单独运行,但我想知道这种方法的整体效率与每个CPU一次只有一个作业。我还可以编写一个更复杂的方法来监视进度并保持每个CPU只占用一个作业(例如在Python中使用多处理),但这会占用昂贵的程序员时间,而且我想知道最终结果是否会真的更快。
答案 0 :(得分:4)
喜欢这么多东西,取决于它。
如果您有I / O或远程处理,例如文件工作,数据库访问,Web服务或其他远程调用,那么通常有足够的空闲CPU时间等待这些完成。在这些情况下,拥有比CPU更多的工作通常是有益的。显然有一些限制,但是在你的“昂贵的程序员时间”下,确定并解决确切的阈值。
在添加进程时,CPU绑定进程很可能会阻塞。
再次针对CPU绑定,而不是您所描述的“推”方法是将其翻转。有一个排队机制,工作线程/进程(每个CPU 1个)从主队列中拉出工作。主队列是轻量级的,当它没有被要求任何东西时进入睡眠状态,工作人员只是在工作中咀嚼。
所有的说法和做法虽然很难在没有更详细地了解问题的情况下给你一个确定的答案。
祝你好运!
答案 1 :(得分:3)
如果您使用线程,使用线程池通常更好。如果你不这样做,你的CPU将被上下文切换堵塞。也就是说,内核显然会使用技巧来确保在所有情况下这都不是问题。
我使用大量CPU功能的(小)进程的经验是,最好将线程数限制为-say-4 *处理器数。通常有一些启动期等,这就是4 *的原因。
如果您使用async-stuff,它可能会自动使用轮询和线程池这样的技巧,这意味着它可以正常工作。我的经验是,异步内容通常比IO线程更好。
答案 2 :(得分:2)
速度方面,你不太可能获得性能提升产生的线程数量超过可用的物理线程,除非你的线程花了很多时间睡觉(在这种情况下它给你的其他线程执行的机会)。请注意,线程休眠可以隐式和隐藏在I / O绑定进程中以及争用锁定时。
这实际上取决于你的线程是否花费大部分时间等待某些事情(例如:更多数据来自服务器,用户做某事,文件更新,获取对锁定资源的访问权限)或者只是尽可能快地并行。如果是后一种情况,使用比实际可用线程更多的线程会降低你的速度。拥有更多线程而不是任务的唯一方法可以帮助提高吞吐量,因为这些线程会浪费时间睡眠,让其他线程在睡眠时有更多的机会。
但是,它可能会使您更容易生成所有这些任务并让操作系统处理调度。
如果线程数量大得多,您可以放慢速度(即使在吞吐量方面)。它在某种程度上取决于你的调度和线程池如何工作以及这些线程是否花费时间休眠,但是线程不一定是构造的便宜的东西,并且具有那么多线程的上下文切换可能比你自己的调度过程更昂贵有很多关于你想要做什么的信息,以及什么时候它比只看到需要执行的大量线程的操作系统更合适。
有一个原因可以解释像英特尔的线程构建模块这样的高效库将池中的线程数与物理硬件相匹配(不多也不少)。它往往是最有效的路线,但考虑到手动调度,工作窃取等需要,它实施起来最笨拙。所以有时候一次只能产生一大堆线程会很方便,但你通常不会这样做是为了优化,除非你在另一个答案中指出I / O绑定,你的线程只是花费大部分时间睡觉并等待输入。
如果你有这样的需求,最有效的方法就是找到一个好的并行处理库(例如:PPL,TBB,OMP等)。然后你只需编写一个并行循环,让库专注于如何最有效地处理线程并平衡它们之间的负载。对于这些类型的案例,您只关注应该执行的任务,但在执行时不一定。