代码之家  ›  专栏  ›  技术社区  ›  user113476

多线程:什么时候创建的线程太多了?

  •  8
  • user113476  · 技术社区  · 16 年前

    我正在开发一个多线程应用程序。

    这个应用程序从一个线程开始,并扩展到多个线程,以实现性能的提高。

    我有一个主线程,它将工作划分为较小的块,并将其卸载到处理块的工作线程。此部分使用信号量控制,一次只允许x个工作线程。工作线程生成数据块,然后存储在队列或环形缓冲区中,然后由一个保存线程读取。此线程负责将数据块保存到磁盘(有时通过本地网络)。

    我的开发机器是8GB内存的四核。在我的机器上运行带有3个工作线程和1个saver线程的应用程序会在网络上产生稳定的数据流,处理器的使用率平均为75%。

    解决这个问题的第二种方法是在工作线程和保护线程之间添加另一组线程(即从当前工作线程中取出一个任务并将其添加到另一个线程中)(我还为每个线程添加一个队列)应用程序在我的计算机上似乎没有任何速度,因为在我的计算机上似乎也没有任何速度。对资源RAM总线饱和和处理器争用的争用较多。

    通过对线程数量及其优先级的大量实验,我找到了处理这个问题的第一和第二种方法的理想机器设置。现在生产机器将有8个内核和64GB的RAM。一个非常不同的环境和应用程序必须为此进行配置。

    我的问题是,你什么时候创建的线程太多了?确定给定机器的理想设置总是一个实验问题吗?是否有一种方法来确定或观察锁是否会从应用程序中带走太多?

    (我不使用线程池,因为它不适合我的需要,因为长时间运行的线程由信号量和其他锁定机制管理。)

    2 回复  |  直到 16 年前
        1
  •  13
  •   cletus    16 年前

    当应用程序的整体性能下降或对运行在同一个框中的其他应用程序的影响受到不可接受的负面影响时,您创建了太多线程。

    关键是没有绝对的答案。

    我正在研究的一个应用程序使用了1000个线程的线程池,对于我们正在做的工作,这似乎是正确的数字。在一个配置中,我们没有限制它,它上升到30000+并且基本上使机器停止研磨。

    基本上,您必须对其进行性能测试,并具有足够的监视/检测功能,以确定应用程序的总吞吐量、资源使用率、线程利用率,并知道线程有多空闲,以及等待队列接收的工作时间有多长。然后根据需要调音。

    一个注意事项:在添加另一层线程之前要仔细考虑。如我所知,编写多线程代码是很困难的。尽量保持简单。添加另一层是一个危险的步骤。

        2
  •  6
  •   Alex Martelli    16 年前

    没有人能给你一个简单的数字答案,因为它太过依赖,不仅取决于机器有多少核心&C,还取决于机器应该和你的应用程序同时做什么其他任务(如果有的话),以及你的线程也在做什么。

    举一个后一个问题的例子:我曾经有过一个非常简单的“爬虫程序”,其中有一些线程专门用于我确定需要的HTTP GET页面——每个线程大部分时间都被阻塞在套接字调用中来执行HTTP GET,因此为了获得相当好的性能,我需要大量的线程(数百个)。后来,我改变了底层方法,使用异步网络I/O而不是阻塞套接字——突然之间,每个线程都可以很容易地有数百个“正在运行”的URL,因此如果有数百个这样的线程处于活动状态,将使系统不堪重负,可能导致打开的套接字比系统能够处理的要多(它不是非常大或配置齐全的服务器!-)导致崩溃,或者至少是由于过度交换等导致的严重减速。

    因此,即使对于完全绑定I/O的线程,它们所使用的I/O的确切形式(例如,阻塞或异步)也会对线程(或进程或任何其他此类单元)的数量对某个整体软件任务的优化产生巨大影响。执行更多CPU绑定工作的线程必须在内核的可用性和内核可以工作的RAM上进行校准(以获得最大性能),但也可能在其他资源上进行校准(例如,如果某些线程能够使用可用的GPU或其他专用处理单元来委派其部分工作)。

    最后,一旦你知道了所有这些参数,你就可以做出一个合理的大概的估计,但是你可能会因为一个重要因素而放弃——所以,在一个实际的工作负载上进行基准测试(比如说,线程的数量是你估计的一半,数量的两倍)应该是最佳的,这是在部署时的性能调整。一般来说,即使对于经验丰富的架构师、开发人员和系统管理员来说,性能行为也常常令人惊讶,因此没有真正好的方法可以替代实际基准、仔细测量和相应调整的经验数据驱动方法。(请注意, 失明的 经验主义——只是试图在没有任何合理模型的情况下适应实验观察结果——几乎和教条主义和教条主义方法一样糟糕,忽略了数据,但这是另一个咆哮;—)。