我正在使用 .NET Framework 4 中的任务并行库(特别是Parallel.For
and Parallel.ForEach
)但是,在并行化某些看起来应该在双核计算机上轻松并行化的任务时,我得到的速度非常平庸。
在分析系统时,由于垃圾收集器的原因,似乎存在大量线程同步。我正在进行大量的对象分配,所以我想知道如何提高并发性,同时最大限度地减少代码重写。
例如,在这种情况下是否有一些有用的技术:
- 我应该尝试手动管理 GC 吗?
- 我应该使用
Dispose
?
- 我应该固定物体吗?
- 我应该做其他不安全的代码技巧吗?
后记:
问题不在于 GC 运行得太频繁,而在于 GC 阻止了并发代码有效地并行运行。我也不认为“分配更少的对象”是一个可以接受的答案。这需要重写太多代码来解决并行性较差的垃圾收集器。
我已经找到了一个有助于整体性能的技巧(使用 gcServer http://blogs.msdn.com/visualizeparallel/archive/2009/12/28/parallel-performance-case-study-finding-references-to-parallel-extensions.aspx)但它对并发性能没有帮助。换句话说Parallel.For
在一项令人尴尬的并行任务中,仅比串行 For 循环快 20%。
后记:
好吧,让我进一步解释一下,我有一个相当大且复杂的程序:优化解释器。它足够快,但我希望在给定并行任务(我的语言中内置的原始操作)时其性能能够随着更多核心可用而很好地扩展。我在评估过程中分配了很多小物体。整个解释器设计基于从单个多态基础对象派生的所有值。这在单线程应用程序中效果很好,但是当我们尝试将任务并行库应用于并行计算时,没有任何优势。
在对任务并行库为何未在这些任务的核心之间正确分配工作进行了大量调查后,罪魁祸首似乎是 GC。显然,GC 似乎是一个瓶颈,因为它在幕后进行了一些我不理解的线程同步。
我需要知道的是:GC 到底在做什么,会导致大量并发的代码在进行大量分配时表现不佳,以及我们如何解决这个问题以外只是分配更少的对象。我已经想到了这种方法,并且需要对大量代码进行重大重写。
如果由于分配/GC 的对象太多而导致 GC 运行过于频繁,请尝试分配更少的对象:)
根据您的场景 - 尝试重用现有对象,创建对象池,使用不会造成太大内存压力的“较轻”对象(或更大的对象以减少分配的对象数量)。
不要尝试通过显式调用 GC.Collect 来“管理 GC”,它很少有回报(里科·马里亚尼这么说 http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx)
or http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)