我正在使用 .NET 框架 4 中的任务并行库(特别是 Parallel.For
和 Parallel.ForEach
),但是在并行化一些看起来应该很容易在双核机器上并行化的任务时,我得到了极其平庸的加速。
在分析系统时,由于垃圾收集器,看起来有很多线程同步正在进行。我正在做大量的对象分配,所以我想知道如何在最小化代码重写的同时提高并发性。
例如,是否有一些技术在这种情况下很有用:
Dispose
? 后记:
问题不是 GC 运行太频繁,而是 GC 阻止并发代码有效地并行运行。我也不认为“分配更少的对象”是可以接受的答案。这需要重写太多代码来解决并行化较差的垃圾收集器。
我已经找到了一个有助于整体性能的技巧( using gcServer ),但它对并发性能没有帮助。换句话说
Parallel.For
在令人尴尬的并行任务中,它仅比串行 For 循环快 20%。POST-POSTSCRIPT:
好的,让我进一步解释一下,我有一个相当大而复杂的程序:一个优化解释器。它足够快,但我希望它在给定并行任务(我的语言中内置的原始操作)时的性能随着更多内核可用而扩展。我在评估期间分配了很多小对象。整个解释器设计基于从单个多态基础对象派生的所有值。这在单线程应用程序中效果很好,但是当我们尝试将任务并行库应用于并行评估时,没有任何优势。
在对为什么任务并行库没有正确地为这些任务跨内核分配工作进行了大量调查之后,似乎罪魁祸首是 GC。显然,GC 似乎充当了一个瓶颈,因为它在幕后进行了一些我不理解的线程同步。
我需要知道的是:GC 在执行大量分配时究竟是做什么会导致大量并发代码执行不佳,以及我们如何解决这个问题,而不仅仅是分配更少的对象。我已经想到了这种方法,并且需要大量重写大量代码。
最佳答案
如果由于分配/GC 的对象太多而导致 GC 运行太频繁,请尝试分配更少的对象:)
根据您的情况 - 尝试重用现有对象,创建对象池,使用不会造成太大内存压力的“较轻”对象(或更大以减少分配的对象数量)。
不要试图通过显式调用 GC.Collect 来“管理 GC”,它很少有返回( Rico Mariani says so )
或 http://blogs.msdn.com/ricom/archive/2003/12/02/40780.aspx
关于.net - 如何在高并发代码中提高 .NET 4.0 的垃圾收集器性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2311154/