C#(单核)不使用所有核

C#(单核)不使用所有核,c#,multithreading,class,parallel-processing,mono,C#,Multithreading,Class,Parallel Processing,Mono,我们正在Mono上运行一个C#项目,我们希望利用多核CPU。我们正在使用System.Threading.Tasks.Parallel.For来实现这一点。但是我们在$top中看到,当我们在8核笔记本电脑上运行时,Mono只使用了350%的CPU(这很奇怪,我们预计是700-800%) 我们试着在没有任何运气的情况下调试它,但是我们发现了一些奇怪的东西。但成功地重现了此代码片段的问题: using System; using System.Threading.Tasks; namespace

我们正在Mono上运行一个C#项目,我们希望利用多核CPU。我们正在使用
System.Threading.Tasks.Parallel.For
来实现这一点。但是我们在
$top
中看到,当我们在8核笔记本电脑上运行时,Mono只使用了350%的CPU(这很奇怪,我们预计是700-800%)

我们试着在没有任何运气的情况下调试它,但是我们发现了一些奇怪的东西。但成功地重现了此代码片段的问题:

using System;
using System.Threading.Tasks;

namespace Cognite.OptimizerMain
{
  public class Triangle
  {
  }

  internal static class Program
  {
    private static void Main(string[] args)
    {
      Console.WriteLine("Starting parallel work");
      double sum = 0.0;
      Parallel.For(0, 5000, node =>
      {
        for (var k = 0; k < 1000000; k++)
        {
          sum += Math.Abs(Math.Cos(k));
          for (var j = 0; j < 5000; j++)
          {
            // var test_triangle = new Triangle();
          }
        }
      });
      Console.WriteLine(sum);
      Console.WriteLine("Ended parallel work");
    }
  }
}
使用系统;
使用System.Threading.Tasks;
命名空间Cognite.OptimizerMain
{
公共阶级三角
{
}
内部静态类程序
{
私有静态void Main(字符串[]args)
{
Console.WriteLine(“开始并行工作”);
双和=0.0;
Parallel.For(0,5000,node=>
{
对于(var k=0;k<1000000;k++)
{
sum+=Math.Abs(Math.Cos(k));
对于(var j=0;j<5000;j++)
{
//var测试_三角形=新三角形();
}
}
});
控制台写入线(总和);
控制台写入线(“结束的并行工作”);
}
}
}
如果按原样运行,它将占用700%-800%的CPU。如果您使用
test\u triangle
取消对该行的注释,那么我们只使用了350%的CPU

我们正在使用这个build命令:
msbuild Optimizer.sln/p:Configuration=Debug
并像这样运行程序
mono program.exe


内存分配/垃圾回收会有问题吗?

您永远不应该分析调试版本,因为在调试版本中有很多代码在发布版本中被删除,这给了您比发布版本更多的行为

您创建的新三角形基本上是无用的,因为它将在发布版本中被删除,因为没有结果将被使用

我没有mono,所以我尝试在windows计算机(.NET Core 2.1)上重现您描述的行为。我也可以通过调试构建看到您描述的行为。 发布版本的cpu使用率接近94%,调试版本的cpu使用率接近56% 线

我预计会发生这种情况,因为在调试构建中

var test_triangle = new Triangle();
被执行。在一个发布版本中,它被优化掉了,这可能导致整个for循环被优化掉了,而编译器可以优化第二个for循环等等,这在调试版本中是不会完成的。必须检查生成的IL代码以验证这一点,我现在懒得这么做。:)


因此,首先您应该对发布版本进行概要分析,其次为了获得更好的测试,您应该在内部循环中执行一些操作,这些操作将在程序结束时使用。为此,优化器无法删除循环。

该程序在Linux上运行的时间是否显著延长?或者CPU使用率是唯一可见的影响?这也需要更长的时间来解决run@FredrikAnfinsen您使用的是哪种版本的Mono,因为在使用
Parallel.ForEach
时,我绝对看不到这一点。你的Parallel.ForEach到底是什么样子的。另外,请不要为代码使用图像,将格式化的代码直接粘贴到您的问题中(图像不可搜索、可索引、在不同屏幕大小上可读、可访问的限制等)@sushingover我使用的是
Mono-JIT编译器版本5.14.0.177
Parallel.ForEach
函数是
system.Threading.Tasks
下的一个系统函数。我怀疑JIT足够聪明,可以在删除
var test_triangle=new triangle()时删除无用的循环行,从而使迭代更快地完成。我不确定这是否足以解释CPU使用率的差异。谢谢你的回复。这只是一个小例子,重现了我们在更大项目中遇到的问题。我们正在构建一个大项目,该项目的核心利用率与调试构建相同。
var test_triangle = new Triangle();