我有 3 个主要处理线程,每个线程都通过 Parallel.Foreach 对 ConcurrentDictionaries 的值执行操作。字典的大小从 1,000 个元素到 250,000 个元素不等
TaskFactory factory = new TaskFactory();
Task t1 = factory.StartNew(() =>
{
Parallel.ForEach(dict1.Values, item => ProcessItem(item));
});
Task t2 = factory.StartNew(() =>
{
Parallel.ForEach(dict2.Values, item => ProcessItem(item));
});
Task t3 = factory.StartNew(() =>
{
Parallel.ForEach(dict3.Values, item => ProcessItem(item));
});
t1.Wait();
t2.Wait();
t3.Wait();
我将此构造的性能(总执行时间)与仅在主线程中运行 Parallel.Foreach 进行了比较,性能提高了很多(执行时间减少了大约 5 倍)
我的问题是:
- 有什么问题吗 上面的方法?如果是,是什么以及如何 可以改进吗?
- 执行时间不同的原因是什么?
- 调试/分析这种情况的好方法是什么?
编辑:为了进一步阐明情况:我正在模拟 WCF 服务上的客户端调用,每个调用都来自一个单独的线程(任务的原因)。我还尝试使用 ThreadPool.QueueUserWorkItem 而不是 Task,但没有提高性能。字典中的对象有 20 到 200 个属性(只有小数和字符串)并且没有 I/O 事件
我通过在 BlockingCollection 中对处理请求进行排队并一次处理一个来解决了这个问题
最佳答案
您可能过度并行化了。
如果您已经在每个任务中使用了良好(且平衡)的并行化,则无需创建 3 个任务。
Parallel.Foreach
已经尝试使用正确数量的线程来充分发挥 CPU 潜力,而不会使其饱和。通过创建具有 Parallel.Foreach
的其他任务,您可能会使其饱和。
(编辑:如 Henk said ,他们可能在协调并行运行时生成的线程数量方面存在一些问题,至少这会导致更大的开销)。
看看here一些提示。
关于c# - 在多个线程上运行 Parallel.Foreach 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5398537/