Parallel.For
和Parallel.ForEach
),然而在一些看起来应该可以轻松并行化的任务上,并行效果却非常平庸,尤其是在双核机器上。在对系统进行分析时,发现由于垃圾回收器存在很多线程同步问题。由于我正在大量分配对象,因此我想知道如何在最小改写代码的情况下提高并发性。例如,在这种情况下是否有一些有用的技术:
- 我应该尝试手动管理GC吗?
- 我应该使用
Dispose
吗? - 我应该固定对象吗?
- 我应该使用其他不安全的代码技巧吗?
问题不在于GC运行太频繁,而在于GC防止并发代码有效地并行运行。我也不认为“分配较少的对象”是一个可接受的答案。这要求改写过多的代码以解决垃圾回收器无法良好并行化的问题。
我已经找到了一个技巧,从总体上提高了性能(使用gcServer),但它并没有提高并发性能。换句话说,在一个明显可以并行处理的任务上,
Parallel.For
只比串行For循环快20%。后后记:
好的,让我进一步解释一下。我有一个相当大且复杂的程序:一个优化解释器。它已经足够快了,但是当给定并行任务(内置于我的语言中的原始操作)时,我希望它的性能随着更多的核心而扩展得更好。在评估过程中,我分配了许多小对象。整个解释器设计基于所有值都来自单个多态基对象。这在单线程应用程序中非常有效,但是当我们尝试将任务并行库应用于并行评估时,就没有优势。
经过大量调查,为什么任务并行库无法正确地在这些任务之间分配工作,看来罪魁祸首是GC。显然,GC似乎成为瓶颈,因为它执行了一些我不理解的后台线程同步。
我需要知道的是:GC到底在做什么,会导致高度并发的代码在进行大量分配时表现不佳,以及我们如何解决这个问题,除了只是分配较少的对象。那种方法已经想到我了,但需要对大量代码进行重写。