【问题标题】:Parallel.For maximum threads and current thread C#Parallel.For 最大线程和当前线程 C#
【发布时间】:2014-01-27 16:45:07
【问题描述】:

我想要达到的目标:

使用Parallel.For(其他任何东西都会受到赞赏,但发现这个是最简单的)我想增加一个名为max的变量,使其使用线程达到100,000,000,但程序应该同时只使用 X 个线程。

代码 sn-p:

using System;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;

using System.Diagnostics;

namespace pool_threading
{
    class MainClass
    {
        static int max=0;
            static int current_max_thread=0;
        public static void Main (string[] args)
        {

            Parallel.For(0, 100000000, new ParallelOptions { MaxDegreeOfParallelism = 50 },
            i =>
            {
                            max++;
                if(Thread.CurrentThread.ManagedThreadId>current_max_thread)
                               current_max_thread=Thread.CurrentThread.ManagedThreadId;
            });

            Console.WriteLine ("I got to this number {0} using most {1} threads",max,current_max_tread);
        }
        public static void GetPage(int i)
        {
        }

    }
}

结果:

我使用最多 11 个线程得到了这个号码 38,786,886

现在......我不知道为什么我得到的数字 38,786,886 小于 38,786,886,但我想这是因为多个线程试图同时增加它,所以如果 10同时尝试,只有第一个才有机会。如果我错了,请纠正我。

最大的“问题”是我一直有 11 个线程,即使最大值设置为 50(滚动代码查看最大值),如果我将其设置为最大 1 个线程,我总是得到 4 个(也许在这种情况下,4 是最小值,但它仍然不能解释为什么我同时得到的最大值只有 11)。

【问题讨论】:

  • 为什么你需要精确的X 线程数?

标签: c# multithreading parallel-processing parallel.foreach


【解决方案1】:

这很简单,只需在循环内使用i,而不是尝试递增并使用max。你没有安全地增加它,但你没有理由尝试。 Parallel.For 的全部要点在于它为您提供循环索引,并确保每个循环索引都被命中一次,不多也不少。

【讨论】:

  • 我只想运行例如一个函数 1000 次,但同时有 X 个线程,不是 1 个线程,也不是 1000 个线程。另外,使用 i 而不是 max 它可以工作。
  • @icebox19 然后使用并行。这就是它的用途,这就是它的作用。
  • 这就是我正在使用的,但它不会同时超过 11 个线程
  • @icebox19 当然可以,为什么要这样做?它将优化自身以使用尽可能多的线程来提供最佳吞吐量。在大多数情况下,这会比您认为的要少。通常,只要比内核多几个线程就可以了。创建额外的线程只会浪费资源并增加争用。使用可以自动处理的东西几乎总是比手动处理要好;你通常不知道最好的。
【解决方案2】:

据我所知,这里发生了两件事:

首先,您正在从多个线程中敲定max。你可能有一台多核机器。这些操作可能彼此重叠。要以线程安全的方式执行递增,您需要

   Interlocked.Increment(ref max);

不是

   max++;   /* not thread safe */

其次,你并不总是得到你在MaxDegreeOfParallelism 中请求的线程数。你永远不会得到更多,但你可能会得到更少。

如果您要使用并行性,请密切注意您将在线程中运行的代码的线程安全性。

【讨论】:

    【解决方案3】:

    我相信您没有获得 50 个线程有两个主要原因:

    1. 硬件。在某个时刻,处理器可以用更少的线程做更多的事情,因为切换线程所花费的时间不仅仅是更频繁地运行一个线程。这导致

    2. 托管代码。 C#.NET 是一个托管代码系统。 .Net 的程序员知道上述内容,并且可能设置了一些限制和检查以防止运行过多的线程。您在代码中设置的内容可能超出了一些内部限制,因此它被有效地忽略了。此外,您设置了一个最大值,因此 Parallel.For() 可以使用 1 到 X 个线程,无论它认为是最有效的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-11
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      • 2012-10-15
      • 1970-01-01
      相关资源
      最近更新 更多