C# 增加并行运行的线程数。对于

C# 增加并行运行的线程数。对于,c#,multithreading,parallel-processing,threadpool,parallel.for,C#,Multithreading,Parallel Processing,Threadpool,Parallel.for,我刚刚用下面的方法做了一个多线程的示例: Console.WriteLine("Number of Threads: {0}", System.Diagnostics.Process.GetCurrentProcess().Threads.Count); int count = 0; Parallel.For(0, 50000, options,(i, state) => { count++; }); Con

我刚刚用下面的方法做了一个多线程的示例:

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();
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();
它在平行线之前给我15根线,在平行线之后给我17根线。因此,只有2个线程被并行占用

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

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();
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
使用相同的线程


那么,如何增加并行运行的线程数呢

并行循环使用硬件CPU核。如果您的CPU有2个内核,这是您可以在机器中获得的最大并行度

期待什么 默认情况下,并行度(即硬件中同时运行的迭代次数)取决于 可用核心数。在典型场景中,您使用的内核越多 有,循环执行得越快,直到达到 阿姆达尔定律预测的收益递减。多快 取决于循环所做的工作类型

进一步阅读:


我面临一个问题,一些数字在并行程序中被跳过。因为当我在并行程序中执行一些繁重而复杂的功能时。因此,这里我想增加最大线程数并覆盖跳过问题

你的意思是:“我的车开得太快时会抖动。我试图通过开得更快来避免这种情况。”这没有任何意义。你需要的是修理汽车,而不是改变速度

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

使用锁是一种选择,也是最容易得到正确答案的方法。但也很难提高效率。您需要的是每次迭代只锁定一小段时间

还有其他实现线程安全的选项,包括使用和方法,而不是使用
Parallel.For()
,如PLINQ或TPL数据流


在确保代码是线程安全的之后,才需要考虑线程数之类的问题。关于这一点,我认为有两件事需要注意:

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

    • 对于没有锁的求和操作,并行循环将给出错误的结果,因为每次迭代的结果取决于单个变量“Count”,并且并行循环中的“Count”值是不可预测的。然而,在并行循环中使用锁并不能实现实际的并行性。因此,您应该尝试其他方法来测试并行循环,而不是求和。

      来自MSDN:“默认情况下,for和ForEach将使用底层调度程序提供的线程数,因此将MaxDegreeOfParallelism从默认值更改为仅限制将使用的并发任务数。”这用于限制线程数量,以避免尽可能多地使用线程。我面临的问题是,并行程序中跳过了一些数字。例如,当我在并行程序中执行一些繁重而复杂的功能时。因此,这里我想增加最大线程数并覆盖跳过问题。我尝试过使用锁,但我认为它不会提供我想要的并行性。因此,这意味着我不需要关心MaxDegreeOfParallelism,因为CPU已经考虑了可用内核的数量。对吗?@RaviSolanki就是这样,你的CPU拥有的核心越多,你的应用程序一次可以执行的并行任务就越多。有趣的是,正如我上面提到的我的查询,我面临一个问题,在并行程序中跳过了一些数字。因为当我在并行程序中执行一些繁重而复杂的功能时。因此,这里我想增加最大线程数并覆盖跳过问题。我试过使用lock,但我认为它不会给我我想要的并行性。@RaviSolanki在并行循环中,迭代没有按顺序执行。并不是说迭代被跳过了,但它们是无序执行的是的,我知道它是以随机顺序执行的。我已经计算了在其中执行的总操作数,我已经设置了50000次迭代,但是在并行之后。因为我已经打印了执行的总迭代数,它显示了37000个数字。我遗漏了什么吗?谢谢你的回答!线程局部变量对于计算Parallel.For执行的迭代非常有用。我也通过了TPL,这似乎对我很有帮助。我已经实现了以下代码。那么我需要在这里实现线程安全吗<代码>变量任务=新任务[计数];对于(var i=0;isomeHeavyOperation();}Task.WaitAll(tasks)@RaviSolanki这在很大程度上取决于
      someHeavyOperation()
      的功能。我正在获取多个URL的HTML流(在我的例子中,它大约是47K)并存储在Azure Blob存储中。