【问题标题】:Memory layout optimization in C#C#中的内存布局优化
【发布时间】:2015-05-25 09:44:31
【问题描述】:

免责声明:下面的措辞中可能存在一些误解,如果我误解了我的代码在 C# 中处理的方式,从我写到它看起来像零和一的那一刻,请纠正我

问题如下(已链接):

在 C# 中,我的数据结构和/或我的数据操作实现是否会对性能产生影响,无论我是否使用优化技术?

编译器在输出IL的时候做了什么,可靠吗? 含义:如果我让我的数据 SOA 会是 IL 中的 SOA 吗?总是?

当 JIT 读取 IL 时,我的数据结构会发生什么变化?它改变了吗?它会自动优化以适合我的处理器吗?

cf:that talk about C/C++

我知道这个演讲是针对原生代码的,并且会讨论处理器布局的细节与原生代码中的数据布局。

我也知道 C# 编译器和 JIT 编译器会针对这些问题为我优化。

基本上我想知道这些优化是否会对我的性能产生影响:

  • SOA 代替 AOS
  • 向量访问模式(在内存中连续访问)
  • 等等...你的名字...

我从事游戏开发工作,性能至关重要,我们处理大量数据,我们需要每秒至少执行 24 次,我不能让 GC 做 300 毫秒的事情,也不能让内存在整个过程中被访问/分配当我试图检测 3000 个不同对象之间的碰撞时的位置

关于我阅读但没有真正回答问题的内容的参考:

但这些并没有回答与处理器和数据布局实现相关的性能成本。


在汉斯回答之后更进一步:

当你说:“你可以追求 SOA,但这无济于事。是的,你的程序会因为所有结构复制而变慢,并且以一种确定性的方式这样做。但这并不能阻止雨。你得到最坏的结果,一个缓慢的程序和完全相同的停顿。”

这并不意味着我的程序不会从 SOA 中受益,它会更快(可能),因为它有助于处理我的数据。只是它不会对 GC 本身产生影响。

另一件事是,如果我不对我的数据布局进行 SOA 或其他改进,编译器不会为我改进,对吗?我不能依赖编译器来处理那种事情?

【问题讨论】:

  • 如果你在谈论这个级别的东西,C#(或任何托管内存环境)可能不适合你。但话又说回来......你是在实时计算、金融计算、大数据等领域工作吗?
  • 实时,但可以正确使用 C# 来提供我希望的那种级别的控制
  • 布局没有根本改变。
  • @GéryArduino 根据定义,Real time 和 Garbage Collector 是互斥的。
  • @Aron 您可以在 C# 中使用一些编程技术,例如对象池/预分配以避免分配(称为 zero alloc / gen zero 在行话中)。甚至还有plugins helping you with this。诚然,这不再是惯用的 C#,它很难正确,它需要广泛的分析,但它肯定可能的。

标签: c# performance memory optimization jit


【解决方案1】:

担心GC就像担心今天会不会下雨一样。迟早要下雨,你无法阻止它。这是必需的,如果不这样做,你就无法保持草坪看起来很绿。你永远不想做的是故意阻止它下雨。因为如果你这样做,它会像洪水一样倾泻而下,把那漂亮的草坪洒掉。你想要的是稳定的毛毛雨。最好是在你不看的晚上。

.NET GC 强烈支持这一点。只有小的 gen #0 和 #1 集合会暂停你的程序。当您的代码继续执行时,昂贵的 gen#2 集合在后台发生。最坏情况下的暂停徘徊在接近一百微秒的地方。这与您的程序将在现代操作系统上暂停的其他原因非常难以区分。就像您的游戏循环因需要运行另一个更高优先级的内核线程而暂时暂停一样。只是毛毛雨,肉眼无法观察到。

您可以追求 SOA,但这无济于事。是的,你的程序会因为所有的结构复制而变慢,并且以一种确定性的方式这样做。但这并不能阻止雨。你得到了两者中最糟糕的,一个缓慢的程序完全相同的停顿。

不用担心下雨,只要确保在正确的时间下雨即可。要利用后台 GC,您需要对数据进行结构化,使其生命周期非常短,因此它很容易在 gen #0/1 集合中消失。或者生活很长时间,所以它在第 2 代找到了一个舒适的家并在那里呆了一段时间。这通常是程序中非常常见的模式,尤其是在游戏中。您几乎不需要做任何事情。

【讨论】:

  • “你可以追求 SOA,但这无济于事”——嗯?我看不出有任何理由说明 GC 会对程序的内存访问模式以及由于缓存等造成的后续影响产生任何影响。至少对于 .NET 4.5(即使使用 SustainedLowLatency 模式),这不是真的没有任何停止世界的 GC - 它们只是比以前更罕见。
  • 不知道您的评论有何相关性,请发表您自己的答案。
  • 我认为 cmets 的一个原因是对答案中发布的事实提出异议并要求澄清或更正,而不仅仅是对答案投反对票。
  • 感谢汉斯的精彩回答,我更新了我的问题,要求澄清
  • SOA 是否更高效尚无定论。这通常不是因为你有太多的 A,而是唯一确定的方法是测量。您确实从抖动(而不是编译器)中获得了帮助,它会努力使 S 尽可能高效。通常的 .NET 指南适用,结构在不超过 4 个成员时是有效的,因此它们适合可用的处理器寄存器。除此之外,复制开始使代码陷入困境。在实践中,结构最终还是在堆上,作为“管理器”类的一个字段。在这种情况下,你根本就没有领先。
猜你喜欢
  • 2012-04-16
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 2014-12-05
  • 2016-06-23
  • 2011-02-14
相关资源
最近更新 更多