在 Parallel.For 中增加 运行 线程数

Increase Number of running thread in Parallel.For

我刚刚使用 This Link 做了一个多线程示例,如下所示:

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);            
int count = 0;
Parallel.For(0, 50000, options,(i, state) =>
{
            count++;                
});

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
Console.ReadKey();

它在 Parellel.For 之前给了我 15 个线程,在它之后只给了我 17 个线程。所以只有 2 个线程被 Parellel.For 占用。

然后我使用 This Link 创建了另一个示例代码,如下所示:

var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Console.WriteLine("MaxDegreeOfParallelism : {0}", Environment.ProcessorCount * 10);
Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);            
int count = 0;
Parallel.For(0, 50000, options,(i, state) =>
{
            count++;                
});

Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
Console.ReadKey();

在上面的代码中,我设置了 MaxDegreeOfParallelism,它设置了 40,但仍然为 Parallel.For 使用相同的线程。

那么如何为 Parallel.For 增加 运行 线程?

并行循环使用硬件 CPU 核心。如果您的 CPU 有 2 个核心,这就是您的机器可以达到的最大并行度

Taken from MSDN:

What to Expect

By default, the degree of parallelism (that is, how many iterations run at the same time in hardware) depends on the number of available cores. In typical scenarios, the more cores you have, the faster your loop executes, until you reach the point of diminishing returns that Amdahl's Law predicts. How much faster depends on the kind of work your loop does.

进一步阅读:

  • Threading vs Parallelism, how do they differ?
  • Threading vs. Parallel Processing

I am facing a problem that some numbers is skipped inside the Parallel.For when I perform some heavy and complex functionality inside it. So here I want to increase the maximum thread and override the skipping issue.

你说的是这样的:"My car is shaking when driving too fast. I'm trying to avoid this by driving even faster."这没有任何意义。你需要的是修理汽车,而不是改变速度。

具体怎么做取决于你在循环中实际做什么。您显示的代码显然是占位符,但即使这样也是错误的。所以我认为你首先应该做的是了解 thread safety.

使用锁是一种选择,也是最容易正确的选择。但也很难使其高效。您需要的是每次迭代只锁定很短的时间。

还有其他方法可以实现线程安全,包括使用 Interlocked, overloads of Parallel.For that use thread-local dataParallel.For() 以外的方法,例如 PLINQ 或 TPL 数据流。


在确保您的代码是线程安全的之后,才该担心诸如线程数之类的问题。关于这一点,我认为有两点需要注意:

  • 对于 CPU 绑定计算,使用比 CPU 拥有的核心数更多的线程没有意义。使用比实际更多的线程通常会导致代码变慢,因为在线程之间切换会产生一些开销。
  • 我认为您无法像那样测量 Parallel.For() 使用的线程数。 Parallel.For() 使用线程池,很可能在循环开始之前池中已经有一些线程。

并行循环会在没有锁的情况下为求和运算提供错误的结果,因为每次迭代的结果都取决于单个变量 'Count',而并行循环中 'Count' 的值是不可预测的。然而,在并行循环中使用锁并不能实现真正的并行。所以,你应该尝试用其他方法来测试并行循环而不是求和。