4

继续从了解 VS2010 C# 并行分析结果的讨论,但更重要的是:

我有许多并行工作的线程(使用 Parallel.For/Each),它们为小类使用许多内存分配。

这会在全局内存分配器线程上产生争用。

有没有办法指示 .NET 为每个线程预分配一个内存池并从这个池中进行所有分配?

目前我的解决方案是我自己的内存池实现(全局分配的 T 类型对象数组,在线程之间回收),这很有帮助,但效率不高,因为:

  1. 我不能指示 .NET 从特定的内存片进行分配。
  2. 我仍然需要多次调用new来为池分配内存。

谢谢,
哈盖

4

3 回答 3

16

I searched for two days trying to find an answer to the same issue you had. The answer is you need to set the garbage collection mode to Server mode. By default, garbage collection mode set to Workstation mode. Setting garbage collection to Server mode causes the managed heap to split into separately managed sections, one-per CPU. To do this, you need to add a config setting to your app.config file.

<runtime>
   <gcServer enabled="true"/>
</runtime>

The speed difference on my 12-core Opteron 6172 was dramatic!

于 2011-06-06T12:00:28.363 回答
0

垃圾收集器不分配内存。

这听起来更像是您分配了许多小的临时对象和一些长期存在的对象,而垃圾收集器正在花费大量时间对临时对象进行垃圾收集,因此您的应用程序不必从操作系统。来自.NET Framework 4 高级开发 - 垃圾收集

只要托管堆中有可用的地址空间,运行时就会继续为新对象分配空间。然而,记忆不是无限的。最终,垃圾收集器必须执行收集以释放一些内存。

解决方案:不要分配很多小的临时对象。垃圾收集和性能页面也可能会有所帮助。

于 2010-05-26T14:00:19.943 回答
0

您可以预先分配一堆对象,并将它们保存在用于单独线程的组中。但是,您可能不会从中获得更好的性能。

垃圾收集器专门设计用于有效处理小型短期对象。如果将对象保存在池中,它们的寿命会很长,并且会在垃圾收集中幸存下来,这反过来意味着它们将被复制到第二代堆中。这种复制将比仅仅分配新对象更昂贵。

于 2010-05-26T14:21:26.130 回答