【问题标题】:Parallel Programming TPL并行编程 TPL
【发布时间】:2011-12-06 05:22:55
【问题描述】:

当您生成多个任务时,如下所示:

 for (int i = 0; i < 1000000; i++) {
        // create a new task
        tasks[i] = new Task<int>((stateObject) => {
            tls.Value = (int)stateObject;

                for (int j = 0; j < 1000; j++) {
                // update the TLS balance
                tls.Value++;
                }

            return tls.Value;
            }, account.Balance);

        tasks[i].Start();
 }

这些任务基本上是在 ProcessThread 上运行的。因此,我们可以为 1,000,000 个任务对 1 个进程线程进行 1,000,000 次切片。

是不是 TPL 任务调度器查看操作系统并确定我们在多核机器中有 8 个虚拟进程线程,然后将 1,000,000 个任务的负载分配给这 8 个虚拟进程线程?

【问题讨论】:

  • 我不确定语法,但逻辑似乎是正确的。我会推荐parallel.for

标签: c# multithreading task-parallel-library


【解决方案1】:

现在任务基本上是在 ProcessThread 上运行的。所以我们可以为 1000000 个任务分割 1 个进程线程 1000000 次。

这不是真的。 Task != 一个线程,尤其不等同于ProcessThread。多个任务将被安排到一个线程上。

是 TPL 任务调度器查看操作系统并确定我们在多核机器中有 8 个虚拟进程线程,因此将 1000000 个任务的负载分配给这 8 个虚拟进程线程吗?

实际上,是的。当使用默认的 TaskScheduler(你在上面做的)时,任务在 ThreadPool 线程上运行。 1000000 个任务不会创建 1000000 个线程(尽管它会使用超过你提到的 8 个......)

话虽如此,通过Parallel.ForParallel.ForEach 通常可以更好地处理数据并行性(例如在巨大的for 循环中循环)。 Parallel 类将在内部使用Partitioner&lt;T&gt; 将工作拆分为更少的任务,这将为您提供更好的整体性能,因为它的开销要少得多。更多详情,请查看我在Partitioning in the TPL上的帖子。

【讨论】:

    【解决方案2】:

    粗略地说,您当前的代码在 ThreadPool 上推送了 1000000 个任务。当这些任务花费大量时间时,您可能会遇到问题。

    在这种情况下,请始终使用

    Parallel.For(0, 1000000, ...);
    

    然后你不仅有调度器,更重要的是还有一个分区器帮助你分配负载。
    更不用说它更具可读性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多