【发布时间】:2016-11-09 15:38:31
【问题描述】:
有一个 C# 函数 A(arg1, arg2) 需要多次调用。为了最快地做到这一点,我正在使用并行编程。
以以下代码为例:
long totalCalls = 2000000;
int threads = Environment.ProcessorCount;
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = threads;
Parallel.ForEach(Enumerable.Range(1, threads), options, range =>
{
for (int i = 0; i < total / threads; i++)
{
// init arg1 and arg2
var value = A(arg1, agr2);
// do something with value
}
});
现在的问题是,这并没有随着内核数量的增加而扩大;例如在 8 核上它使用 80% 的 CPU,在 16 核上它使用 40-50% 的 CPU。我想最大限度地使用CPU。
您可以假设A(arg1, arg2) 内部包含一个复杂的计算,但它没有任何 IO 或网络绑定操作,也没有线程锁定。还有哪些其他方法可以找出代码的哪一部分使其无法以 100% 并行方式执行?
我也试过增加并行度,例如
int threads = Environment.ProcessorCount * 2;
// AND
int threads = Environment.ProcessorCount * 4;
// etc.
但这没有任何帮助。
更新 1 - 如果我通过将 A() 替换为计算素数的简单函数来运行相同的代码,那么它使用了 100 个 CPU 并且可以很好地扩展。所以这证明了另一段代码是正确的。现在问题可能在原始函数A() 内。我需要一种方法来检测导致某种排序的问题。
【问题讨论】:
-
使用
Tasks 而不是Parallel.ForEach会不会更好?然后,您可以更好地控制任务及其数量。 -
哪个操作系统?您是否正在运行没有 vshost.exe 的发布版本?当您测量 CPU 使用率时,该进程是唯一运行的进程吗?进程优先级?
-
@dlatikay - Windows Server 2012。是的,我正在运行发布版本,除了默认操作系统功能之外,这是唯一正在运行的程序。我没有设置优先级。让我也试试。
-
@Liam Tasks API(Task 或 Parallel.For(Each))实现线程池。因此,使用
MaxDegreeOfParallelism不应该与使用多个任务一样有效吗? -
@Liam - 会尝试并更新结果。
标签: c# task-parallel-library cpu-usage parallel.foreach