我们有一个批处理过程,包括在每行数据上发生的大约5次计算(总计2000万行)。我们的生产服务器将拥有大约24个具有不错CPU的处理器。
性能对我们至关重要。假设我们的算法非常有效,那么实现最大时间性能的最佳方法是什么?具体来说,我们是否应该通过多线程,使用线程池等来实现更好的性能?另外,可以使用Process对象将批处理分成多个程序有益吗?
答案 0 :(得分:4)
一些想法:
首先,你需要更加明确地围绕“最佳” - 在执行如此大规模的处理时需要权衡利弊。具体而言,内存,I / O和CPU利用率是考虑因素。每个计算需要多少内存。等等。
假设您是计算机上唯一的进程,您拥有大量内存,并且您主要对优化吞吐量感兴趣,以下是一些建议:
除了线程池之外,还有Task Parallel Library,它提供了简化这种并行计算开发的工具。它专门设计用于扩展核心数量并优化线程的使用方式。还有Parallel LINQ,你也可能觉得它很有用。
答案 1 :(得分:2)
总的来说,如果你可以等待.NET 4,PFX(并行扩展)可能是最好的模型。
直到那时避免大量的进程/线程开始/结束,即。使用threadpool(启动一个进程非常昂贵,启动一个线程非常昂贵)。
简单的方法:将计算批处理应该在~50ms内完成的作业,然后开始排队。困难的部分是确保一切都已完成。一个简单的完成将是一个共享的“完成”计数器,每个作业递增它。主线程在读取计数器时旋转,直到达到预期的最终值。
答案 2 :(得分:1)
这很大程度上取决于“5计算”的构成。如果执行这5个计算需要任何重要的计算,那么多线程将是一个巨大的好处。工作量越小,进行分区就越需要小心,以获得良好的收益。
鉴于这是“在每行数据上运行”,处理此行(如果可能)的最有效方法是直接在数据库中更新它。拉动数据客户端,处理和重新填充将比尝试直接在DB中进行计算慢得多。大多数数据库服务器都会自行支持线程,并且可以很好地优化更新,因此如果您可以直接在数据库中处理数据,那么您将获得最佳性能。
如果那是不可能的,那么我建议使用Task Parallel Library来处理这个问题。在.NET 4上运行将特别有用,因为添加到线程池的工作窃取将为您提供更好的整体吞吐量。
答案 3 :(得分:0)
Threadpools是一种安全且简单的方法 - 池中最多可同时使用64个线程(这实际上是WaitHandles的限制)。使用Process对象只会引入围绕调试的新问题和复杂性,这些问题并不值得进行权衡 - 尤其是考虑到您获得的任何价值都来自池将为您提供的并行性。
答案 4 :(得分:0)
只有细粒度的评估才能揭示优化任务的最佳方式,但使用线程池肯定会带来改进。 发现最常见的任务并将其划分到池中。重要的是,衡量绩效的关键方法, 只有这样才能知道瓶颈在哪里以及在哪里进行改进。
答案 5 :(得分:0)
如果可能的话,我建议在数据库过程中执行此操作。否则,客户端处理的效率可能无关紧要,时间将通过在网络上来回编组数据来控制。即使您在同一台计算机上运行该进程,也可能会因为(可能是ODBC)驱动程序而导致序列化所有内容。当然,除非您编写可以在数据库服务器的地址空间内运行的本机过程(如果您的服务器支持该过程)。
我想我建议编写一个程序,它选择记录的下限和上限,然后编写一个客户端程序,分离几个线程,为每个线程分配一个DB连接,然后调用服务器端具有适当大小边界的程序(比如五个线程,每个四百万行)。如果您的数据库服务器是多线程的,那么这应该会给您带来不错的性能。
但是,对于任何多线程方法,请注意,如果您要更新许多行,如果您不经常提交事务,则可能因锁定升级而导致锁定问题。
答案 6 :(得分:0)
如果您使用的是SQL Server 2005/2008,请考虑将计算作为CLR函数添加到SQL Server:http://msdn.microsoft.com/en-us/library/ms254498%28VS.80%29.aspx。这比在T-SQL中进行计算要快得多,并且可以节省将数据移入和移出数据库的成本。 SQL Server将为您管理线程。您还可以尝试打开多个连接,每个连接处理一组不同的行,以衡量对性能,连接时间等的影响。