C# C语言中的线程内存管理#

C# C语言中的线程内存管理#,c#,memory-management,parallel-processing,contention,C#,Memory Management,Parallel Processing,Contention,继续讨论,但要更切题: 我有许多并行工作的线程(使用parallel.For/Each),它们为小型类使用许多内存分配 这会在全局内存分配器线程上创建争用 有没有一种方法可以指示.NET为每个线程预先分配一个内存池,并从该池执行所有分配 目前,我的解决方案是我自己的内存池实现(T型对象的全局分配数组,在线程之间循环使用),这有很大帮助,但效率不高,因为: 我无法指示.NET从特定内存片进行分配 我仍然需要多次调用new来为池分配内存 谢谢, Haggai垃圾收集器不分配内存 这听起来更像是你在分

继续讨论,但要更切题:

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

这会在全局内存分配器线程上创建争用

有没有一种方法可以指示.NET为每个线程预先分配一个内存池,并从该池执行所有分配

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

  • 我无法指示.NET从特定内存片进行分配
  • 我仍然需要多次调用new来为池分配内存
  • 谢谢,

    Haggai

    垃圾收集器不分配内存

    这听起来更像是你在分配很多小的临时对象和一些长寿命的对象,垃圾收集器花费大量时间对临时对象进行垃圾收集,这样你的应用程序就不必从操作系统请求更多内存。发件人:

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


    解决方案:不要分配太多小的临时对象。上的页面可能也会有所帮助。

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


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

    我搜索了两天,试图找到你遇到的同一问题的答案。答案是您需要将垃圾收集模式设置为服务器模式。默认情况下,垃圾收集模式设置为工作站模式。 将垃圾收集设置为服务器模式会导致托管堆拆分为单独的托管部分,每个CPU一个。 为此,您需要将配置设置添加到app.config文件中

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

    我的12核Opteron 6172的速度差异是巨大的

    有没有可能将T设为值类型并在堆栈而不是堆上分配它?这里的问题是什么。你的程序运行缓慢吗?内存不足(崩溃)?只是用了很多内存?@tehMich:我不这么认为。这些对象是复合类,将它们分解为单独的变量或数组会很麻烦。此外,它们需要大量的内存,我不确定它们是否能放在堆栈中(我说的是几十兆字节的数量)。@Lasse V.Karlsen:问题是内存分配上的争用会减慢程序的速度。你的第一段正是我目前的解决方案。由于我在整个程序中多次循环使用这些对象以获得许多线程,因此我认为复制到第二代堆在这种情况下是无关紧要的。我如何检查它是否是?我的应用程序的内存需求确实很大(几GB),但我有一个8GB的RAM,GC收集会话大约每分钟只发生一次,并且非常短。“GC收集会话大约每分钟只发生一次,非常短”似乎与此矛盾“大部分同步时间都花在等待GC线程完成内存分配上”,这是你在另一篇文章中提到的。现在这是新闻,我不知道你可以这样调整GC。我将在我自己的代码中尝试一下,非常有兴趣看看它会做什么!