Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 大批量过程的多线程问题_C#_Multithreading_Process_Threadpool - Fatal编程技术网

C# 大批量过程的多线程问题

C# 大批量过程的多线程问题,c#,multithreading,process,threadpool,C#,Multithreading,Process,Threadpool,我们有一个批处理过程,包括对每行数据(总计2000万行)进行大约5次计算。我们的生产服务器将有大约24个处理器,并配备像样的CPU 性能对我们至关重要。假设我们的算法非常有效,那么实现最大时间性能的最佳方法是什么?具体来说,我们是否应该通过多线程、使用线程池等实现更好的性能?另外,使用Process对象将批处理划分为多个程序是否有好处?线程池是一种安全且简单的方法-池最多可同时使用64个线程(这实际上是WaitHandles的限制)。使用Process对象只会带来调试方面的新问题和复杂性,而这些

我们有一个批处理过程,包括对每行数据(总计2000万行)进行大约5次计算。我们的生产服务器将有大约24个处理器,并配备像样的CPU


性能对我们至关重要。假设我们的算法非常有效,那么实现最大时间性能的最佳方法是什么?具体来说,我们是否应该通过多线程、使用线程池等实现更好的性能?另外,使用Process对象将批处理划分为多个程序是否有好处?

线程池是一种安全且简单的方法-池最多可同时使用64个线程(这实际上是WaitHandles的限制)。使用Process对象只会带来调试方面的新问题和复杂性,而这些问题和复杂性并不值得权衡——特别是考虑到您获得的任何价值都将来自于池将为您提供的并行性。

总体而言,如果您可以等待.NET 4,PFX(并行扩展)可能是最好的模型

在此之前,避免大量的进程/线程开始/结束,即使用线程池(启动进程非常昂贵,启动线程非常昂贵)


简单的方法是:将计算批量到作业中,这些作业应在大约50毫秒内完成,然后开始排队。困难的部分是确保一切都已完成。一个简单的完成方法是使用一个共享的“completed”计数器,每个作业都递增它。主线程在读取计数器时旋转,直到达到预期的最终值。

这在很大程度上取决于“5次计算”的构成。如果执行这5个计算需要进行任何重要的计算,那么多线程将是一个巨大的好处。工作量越小,为了获得良好的收益,在分区方面就越需要小心

考虑到这是“在每一行数据上”运行的,处理它的最有效方法(如果可能的话)是直接在数据库中更新它。拉入数据客户端、处理和重新填充将比直接在数据库中进行计算慢得多。大多数数据库服务器本身都有很好的线程支持,并且在优化更新方面做得很好,因此,如果您能够直接在数据库中处理数据,您将获得最佳性能

如果这是不可能的,那么我建议考虑使用来处理这个问题。在.NET 4上运行会特别有帮助,因为添加到线程池中的工作将为您提供更好的总体吞吐量。

一些想法:

首先,您需要对“最佳”有一点更明确的定义——在执行如此大规模的处理过程中需要权衡。具体来说,内存、I/O和CPU利用率是需要考虑的因素。每次计算需要多少内存。等等

假设您是机器上唯一的进程,您有大量内存,并且您主要对优化吞吐量感兴趣,以下是一些建议:

  • 您肯定需要某种方式的多线程处理
  • 线程池是一种合理的方法,但您需要确保I/O延迟不是最耗时的步骤
  • 您可能希望使用移交过程将计算与持久化计算结果分开。您可能还希望对结果进行批处理,以减少到数据库的往返次数
  • 您还需要将记录批量加载到内存中,以尽量减少对数据库的访问
  • 尽可能避免阻塞操作和其他内存障碍,以减少锁定争用

除了线程池之外,还有,它为简化此类并行计算的开发提供了便利。它是专门设计用来扩展内核数量和优化线程使用方式的。还有一些,您可能也会发现它们很有用。

只有精细的评估才能揭示优化任务的最佳方法,但使用线程池肯定会带来改进。 发现最常见的任务并在池中进行划分。重要的是,衡量绩效的关键方法,
因为只有这样,我们才能知道瓶颈在哪里,以及需要改进的地方。

如果可能的话,我建议在数据库过程中这样做。否则,不管客户端处理的效率有多高,时间主要是通过在网络上来回整理数据。即使您在同一台机器上运行该进程,也可能会受到通过(大概是ODBC)驱动程序序列化所有内容的惩罚。当然,除非您编写了可以在数据库服务器的地址空间内运行的本机过程(如果您的服务器支持)

我想我建议编写一个程序,该程序在选择记录时采用上下限,然后编写一个客户端程序,该程序分叉几个线程,为每个线程分配一个DB连接,然后以适当大小的边界调用服务器端程序(例如,五个线程,每个线程400万行)。如果您的DB服务器是多线程的,那么这将为您提供良好的性能


使用任何多线程方法,请注意,如果您正在更新多行,则如果您不经常提交事务,则会由于锁升级而导致锁定问题。

< P>如果使用SQL Server 2005/2008,请考虑将计算添加到SQLServer作为CLR函数:这比在T-SQL中进行计算要快得多,并节省了将数据移入和移出数据库的成本。SQL Server将为您管理线程。您还可以尝试打开多个连接,每个连接处理不同的行集,以评估对性能的影响