我们正在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");
}
}
}
如果按原样运行,它将占用700%-800%的CPU。如果您取消对test_triangle
的注释,那么我们将仅使用350%的CPU。
我们正在使用以下构建命令:msbuild Optimizer.sln /p:Configuration=Debug
,并像这样mono program.exe
内存分配/垃圾回收有问题吗?
答案 0 :(得分:0)
您永远不应该剖析调试版本,因为在调试版本中,很多代码会在发行版本中删除,并且给您带来除发行版本之外的其他行为。
您创建的新Triangle基本上是无用的,因为它将在发布版本中删除,因为将不会使用任何结果。
我没有单声道,所以我尝试在Windows计算机(.NET Core 2.1)上重现您描述的行为。通过调试版本,我也可以看到您描述的行为。 在发布版本中,我的CPU使用率接近94%,在调试版本中,CPU的使用率达到56% 线
var test_triangle = new Triangle();
我希望发生这种情况是因为在调试中建立了行
var test_triangle = new Triangle();
被执行。在发行版本中,它已经进行了优化,这可能导致优化整个for循环,而编译器则可以优化第二个for循环,依此类推,这在调试版本中不会完成。必须检查生成的IL代码以验证这一点,我现在太懒了。 :)
因此,首先您应该概要分析发行版本,其次要进行更好的测试,您应该在内部循环内执行一些操作,以在编程结束时使用。为此,优化器无法删除循环。