Hyper-V PLINQ 虚拟机并行问题

Hyper-V PLINQ Virtual Machine Parallel issue

我有一个 PLINQ 查询...

batch
.AsParallel()
.WithExecutionMode(ParallelExecutionMode.ForceParallelism)
.WithCancellation(cancellationToken);
.Select(i => new { instruction = i, accountKey = new AccountKey(i.x, i.y, i.z) })
.GroupBy(x => x.accountKey)
.ForAll(grouping =>
{
    foreach (var instructionBatch in grouping.OrderBy(i => i.instruction.FileRow).Select(i => i.instruction))
    {
        // High CPU method.
    }
});

一个批次可以有10000条记录。这些调用 High CPU 方法,后者又调用 Web 服务并将信息保存到数据库。

在我的物理 64 位 pc i7-4770 CPU @ 3.40 GHz 16.0GB 内存上。此代码所在的服务 运行 启动了大约 32 个线程,占用了大约 150,000 - 200,000 KB 的内存使用量。

在 64 位虚拟机 E5-2630 v3 @2.40GHz 的 Hyper-V 测试环境中,它生成超过 200 个线程,内存接近 2GB 限制。

它启动这么多线程以及虚拟机上的内存没有释放的原因是什么?

我需要使用 WithDegreeOfParallelism 吗?如果这个过程可以同时调用 4 个不同的批次(例如 1 x 1 条记录、1 x 100 条记录、1 x 1000 和 1 x 10,000)这是否意味着当我指定 WithDegreeOfParallelism 时,4 个批次将分别触发线程数,甚至是 1 条记录的批次?

感谢您的帮助。

TPL Parallel 和 PLINQ 工具不擅长处理 IO。他们倾向于选择糟糕的线程数。这些方法采用的线程数是启发式驱动的。我相信这是包含此启发式的线程池。

在玩 IO 时,我强烈建议使用 WithDegreeOfParallelism。您可以使用 Environment.ProcessorCount。如果涉及 IO,您可能希望稍微超额订阅并添加恒定数量的线程。

在 PLINQ 中 WithDegreeOfParallelism 是一个绝对数量。不多也不少。所以是的,4 个并发查询导致 4 倍的线程数。我相信内置的自动线程计数启发式算法不会发生此问题。

考虑对所有并发查询使用固定的并发性TaskScheduler

这是一个实验:运行 以 Thread.Sleep(1000000) 循环。你会发现大量的线程。可能,每 500 毫秒一个。这是线程池在认为需要更多线程以避免死锁和提高利用率时注入线程的方式。完全不适合IO。

最后 运行 性能监视器我注意到在虚拟化环境中,性能计数器 # of Exceps Thrown / Sec 显示出非常高的数字。我遵循 http://blogs.msdn.com/b/spike/archive/2011/06/23/how-to-figure-out-what-exception-is-causing-a-high-number-in-of -exceps-thrown-sec-using-procdump-and-windbg.aspx 并确定在尝试连接到 mysql 数据库时抛出了未处理的异常。这是由于防火墙规则没有到位。

关于并行度。 High CPU 方法下方的第二个触发后遗忘任务开始生成字母。然而这并没有 任何 exception/logging 处理它。这是抛出错误的地方。为了克服这个问题,我将 await Task.Run 包裹在一个 try catch 中。