C# 使用更多线程会带来较小的性能提升,使用更多应用会带来较大的性能提升
我的应用程序是一个蛮力优化器。为了提高性能,我决定使用多线程。这个任务很容易并行化——分割搜索空间,为每个块使用一个线程,然后合并结果 在我有12个虚拟内核的CPU上,使用多线程的加速比在5个线程时达到230%。我没有能够显示缓存未命中的探查器,当应用程序搜索不适合缓存的对象时,我认为缓存是瓶颈 然后我在多个实例中启动了应用程序,每个实例有5个线程。每个实例的平均运行时间几乎与单独运行的一个实例的运行时间相同。因此,在没有代码的情况下,我的速度提高了3倍,而且缓存似乎不是问题所在 我的问题如下:C# 使用更多线程会带来较小的性能提升,使用更多应用会带来较大的性能提升,c#,multithreading,performance,caching,C#,Multithreading,Performance,Caching,我的应用程序是一个蛮力优化器。为了提高性能,我决定使用多线程。这个任务很容易并行化——分割搜索空间,为每个块使用一个线程,然后合并结果 在我有12个虚拟内核的CPU上,使用多线程的加速比在5个线程时达到230%。我没有能够显示缓存未命中的探查器,当应用程序搜索不适合缓存的对象时,我认为缓存是瓶颈 然后我在多个实例中启动了应用程序,每个实例有5个线程。每个实例的平均运行时间几乎与单独运行的一个实例的运行时间相同。因此,在没有代码的情况下,我的速度提高了3倍,而且缓存似乎不是问题所在 我的问题如下:
List<QSettings> xSplittedSettings = mxSettings.split(xThreadCount);
List<Task<QResults>> xTasks = new QList<Task<QResults>>();
for (int xThreadIdx = 0; xThreadIdx < xThreadCount; xThreadIdx++)
{
int xThreadIdx_ = xThreadIdx;
xTasks.add(Task.Factory.StartNew<QResults>(() => performMainCycle(mxCandidate.clone(), xSplittedSettings[xThreadIdx_])));
}
Task.WaitAll(xTasks.toArray());
List xSplittedSettings=mxSettings.split(xThreadCount);
List xTasks=new QList();
对于(int-xThreadIdx=0;xThreadIdxperformMainCycle(mxCandidate.clone(),xSplittedSettings[xThreadIdx_]));
}
Task.WaitAll(xTasks.toArray());
我已经检查过,当运行多个线程时,每个线程只计算问题的相应部分。我还检查了所有线程是否同时计算。但是,当有一个实例有5个线程时,任务管理器显示的CPU使用量仅超过15%
任何暗示都非常感谢,
Daniel多线程问题对于诊断来说既困难又复杂。这需要对你的钻孔申请进行更深入的检查,不仅仅是这样的代码和平。小心使用
Task.Factory.StartNew
而不指定TaskSchedueller
它将使用TaskSchedueller.Current
如果您不传入一个,并且您可能会将要在UI线程而不是线程池上完成的工作排队,始终传入TaskSchedueller.Default
以确保它进入线程池,或者只使用Task.Run
@ScottChamberlain:感谢您指出这一点。我试着摆弄TaskCreationOptions和TaskScheduler。默认情况下,基本上一切都是一样的(TaskCreationOptions有一些明显的改进。没有,但10个线程仍然消耗约30%的CPU)。多线程问题对于诊断来说既困难又复杂。这需要对你的钻孔申请进行更深入的检查,不仅仅是这样的代码和平。小心使用Task.Factory.StartNew
而不指定TaskSchedueller
它将使用TaskSchedueller.Current
如果您不传入一个,并且您可能会将要在UI线程而不是线程池上完成的工作排队,始终传入TaskSchedueller.Default
以确保它进入线程池,或者只使用Task.Run
@ScottChamberlain:感谢您指出这一点。我试着摆弄TaskCreationOptions和TaskScheduler。默认情况下,基本上一切都是一样的(TaskCreationOptions有一些明显的改进。没有,但10个线程仍然消耗约30%的CPU)。