【问题标题】:Parallelization Considerations并行化注意事项
【发布时间】:2010-11-19 17:21:32
【问题描述】:

我想了解社区对此的看法。如果我有一个严重依赖 DB/IO 的进程,那么使用 Task Parallel 库并行化各个进程路径有多聪明?

我举个例子……如果我有一堆物品,我需要做以下操作

  1. 在数据库中查询项目列表
  2. 执行一些聚合操作以根据动态参数列表对某些项目进行分组。
  3. 对于每个分组结果,根据聚合结果在数据库中查询某些内容。
  4. 对于每个分组的结果,进行一些数值计算(3 和 4 将依次发生)。
  5. 对#3 中计算的结果进行一些插入和更新
  6. 对 #1 中返回的每个项目进行一些插入和更新

从逻辑上讲,我可以在步骤#3、#5、#6 中并行化成任务图,因为其中一项与前一项的结果无关。但是,它们中的每一个都将在数据库(sql server)上等待,这很好,我知道我们只能处理 SQL server 允许的范围。

但我想在本地机器上合理地分配任务,以便它以数据库允许的速度处理,而不必等待我们结束任何事情。我做了一些模拟原型,我用 Thread.Sleeps 替换了 db 调用(我还尝试了 .SpinWait 的一些变体,它快了一百万倍),并且并行版本比当前完全串行的实现快得多而且根本不平行。

我担心的是给 SQL 服务器带来过大的压力……在我走得太远之前,有什么需要考虑的吗?

【问题讨论】:

    标签: c# sql-server multithreading task-parallel-library


    【解决方案1】:

    如果并行版本比串行版本快得多,我不会担心您的 SQL 服务器的压力......当然,除非您正在执行的任务与其他一些重要或时间关键的操作相比优先级较低也在数据库服务器上执行。

    我不太了解您对任务的描述,但听起来应该更多的任务应该直接在数据库中执行(我想有一些细节使得这不可能?)

    【讨论】:

      【解决方案2】:

      另一种选择是创建一个管道,以便第二组的步骤 3 与第一组的步骤 4 同时发生。如果您可以在第 5 步重叠更新,也可以这样做。这样您就可以进行并发 SQL 访问和处理,但不会对数据库造成过多负担,因为您一次只能进行两个并发操作。

      因此,您按顺序执行第 1 步和第 2 步(我假设)以获得需要进一步处理的组集合。然后。你的主线程开始了:

      for each group
        query the database
        place the results of the query into the calc queue
      

      第二个线程为结果队列提供服务:

      while not end of data
        Dequeue result from calc queue
        Do numeric calculations
        place the results of the query into the update queue
      

      第三个线程服务于更新队列:

      while not end of data
        Dequeue result from update queue
        Update database
      

      System.Collections.Concurrent.BlockingCollection<T> 是处理这类事情的一个非常有效的队列。

      这里的好处是,如果您可以通过添加多个计算线程或查询/更新线程来扩展它,如果 SQL Server 可以处理更多并发事务。

      我在日常合并/更新程序中使用了与此非常相似的东西,效果非常好。该特定进程不使用 SQL 服务器,而是使用标准文件 I/O,但概念转换得很好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-16
        相关资源
        最近更新 更多