要创建多少个线程?

时间:2009-11-24 03:11:22

标签: c++ multithreading optimization

我正在学习如何编写mutithreaded程序,我有一个假设的问题,关于程序的最佳线程数。

让我描述两个场景。

第一种情况是我有一个容易多线程的程序,但是每个线程都要做很多工作(每个线程的执行时间大约是几秒)。

第二种情况是我有一个程序,它也很容易多线程但每个线程的执行时间非常短,大​​约为毫秒。

在这些场景中的任何一个场景中,对程序进行多线程处理的最有效方法是什么?它是创建与我的系统内存允许的一样多的线程,还是在创建新线程之前等待线程完成,这样我在任何时候都只能运行4个工作线程的格言。

一方面,许多线程可能会遇到线程在线程之间切换的开销问题(根据我的理解,这不是一个如此严重的开销)。另一方面,如果我限制运行的线程数,这意味着我将运行额外的检查条件并锁定和解锁计数器变量以跟踪运行的线程数,并在旧线程完成时创建新线程

我可以看到,如果有很多小线程,最好简单地用尽可能多的线程重载我的系统,因为在线程完成运行之前不会有太多的线程切换。这将节省我不断跟踪线程数量的开销。

另外,如果只有几个大线程(少数,我的意思是大约一百个大线程),跟踪线程是有意义的,这样我们就可以保持线程处于最佳数量,这样就可以了非常多的线程切换(因为开销会更大,因为我们可能会在单个线程完成之前多次切换)。

那么这些假设对于每个案例都是正确的,还是有一种在所有情况下都是正确的做事的普遍方式?

注意:这是假设一个多核心系统(现在,让我们忽略超线程)并让我们忽略与mutithreading相关的任何典型问题(假设所有线程都有私有写入位置,并且只能读取公共位置,锁定和解锁仅在递增或递减活动线程数的计数器时发生。)

谢谢,

-Faken

6 个答案:

答案 0 :(得分:5)

场景#1:创建n个线程,其中“n”是CPU核心数

场景#2:相同,但不是一直创建和终止线程,而是使用基于工作项/线程池的方法,就像.NET Parallel Framework那样。

修改:这是一篇涵盖#2的好文章 - http://msdn.microsoft.com/en-us/magazine/cc163340.aspx;让PFx计算出要运行的线程数,您只需描述任务之间的相互关系。

答案 1 :(得分:2)

通常的做法是使线程计数可配置,并在多个配置中分析应用程序性能。

另请注意,在许多情况下,这不是与许多线程或上下文切换相关的开销,而是由于同步对共享资源的访问导致多线程应用程序效率低下而导致的瓶颈。即使你认为你的代码是防死锁的,如果有很多IO正在进行,那么糟糕的同步实现可能会有效地扼杀你并行化所带来的任何好处。

答案 2 :(得分:2)

这不是一个难以回答的问题的答案,但有几点:

由于你的帖子很短暂,也许你应该考虑使用池来管理它们?您可以创建一个包含许多适合主机系统和任务配置文件的线程的池(比如每个核心开始使用一个)并将其提供给某种类型的队列。通过这样做,您可以消除启动新线程的开销,为每个任务分配每个线程的堆栈等。

对于池的适当线程数,这取决于您正在运行的任务类型。如果它们是CPU绑定任务,则每个CPU一个线程非常适合:当您不需要时,可以避免上下文切换。另一方面,如果它们是IO绑定任务,比如执行套接字通信的线程,那么您可能希望将该数字加倍,例如,这样您可以在等待IO输入时更好地使用处理器。

无论如何,总之,对于这种东西,没有一种通用的方法。与以往一样,对您的代码进行分析,以找出效率低下的位置,并根据您的结果对其进行调整。

答案 3 :(得分:1)

假设你的意思是一个Windows程序,即使它是一个C ++而不是一个dot-Net程序,它还是会让你在开始之前浏览一下Joe Duffy的“Windows上的并发编程”。他很好地使用了Windows提供的线程池例程,最令人信服的是因为他们已经在内部调整处理器配置,从而减轻了你的负担。 如果你继续自己动手,那么整本书中讨论的问题肯定会让你绊倒标准陷阱。

答案 4 :(得分:0)

我会从一个足够好的数字开始,然后收集统计信息以找出要运行的正确线程数以获得良好的性能。

答案 5 :(得分:0)

线程并不便宜。我基本上知道使用它们的两个原因:

  1. 要使多个硬件并行工作,无论它们是CPU核心,磁头,其他类型的机器,还是世界另一端的服务器。

  2. 让多个人并行工作,例如拥有自己会话的用户。这里的优点不是速度,而是编码每个用户的交互顺序的简便性。

  3. 或者两者兼而有之,例如,如果你有一个线程要处理,一个线程要响应用户。

相关问题