【发布时间】:2011-01-19 15:34:53
【问题描述】:
我正在使用 .NET 框架 4 中的任务并行库(特别是 Parallel.For 和 Parallel.ForEach),但是在并行化一些看起来应该可以轻松并行化的任务时,我的速度提升非常平庸。核心机。
在分析系统时,由于垃圾收集器的原因,看起来有很多线程同步正在进行。我正在做大量的对象分配,所以我想知道如何在最大限度地减少代码重写的同时提高并发性。
例如,在这种情况下是否有一些有用的技术:
- 我应该尝试手动管理 GC 吗?
- 我应该使用
Dispose吗? - 我应该固定对象吗?
- 我应该做其他不安全的代码技巧吗?
后记:
问题不在于 GC 运行太频繁,而在于 GC 阻止了并发代码高效地并行运行。我也不认为“分配更少的对象”是一个可以接受的答案。这需要重写太多的代码来解决并行化不佳的垃圾收集器。
我已经找到了一个有助于提高整体性能的技巧 (using gcServer),但它对并发性能没有帮助。换句话说,在令人尴尬的并行任务中,Parallel.For 仅比串行 For 循环快 20%。
后置脚本:
好的,让我进一步解释一下,我有一个相当大而复杂的程序:优化解释器。它足够快,但我希望它在给定并行任务(内置于我的语言中的原始操作)时的性能能够在更多内核可用时很好地扩展。我在评估期间分配了很多小对象。整个解释器设计基于从单个多态基础对象派生的所有值。这在单线程应用程序中效果很好,但是当我们尝试将任务并行库应用于并行评估时,就没有优势了。
在对为什么任务并行库没有为这些任务正确地跨内核分配工作进行大量调查之后,罪魁祸首似乎是 GC。显然 GC 似乎充当了瓶颈,因为它在后台执行了一些我不明白的线程同步。
我需要知道的是:GC 到底在做什么会导致大量并发代码在执行大量分配时表现不佳,以及我们如何解决这个问题除了只是分配更少的对象。我已经想到了这种方法,并且需要大量重写大量代码。
【问题讨论】:
-
是否可以发布实际代码,或者至少是它的代表?我认为我们需要深入研究细节以帮助您...
-
代码将完全无法理解。这是优化解释器的一个非常深的部分。
-
“非常平庸”?那可能吗? ;)
-
任务有多“小”,它们需要多少协调/通信/全局数据?尽管有任何 GC“开销”,但所有这些都很容易导致非并行有用的循环。祝你好运!
-
一个想法,可能完全不相关:您尝试过发布版本还是仅使用调试版本进行测量?
标签: .net performance concurrency garbage-collection parallel-processing