【问题标题】:C# vs C/C++: do I need to order struct fields manually for best performance?C# vs C/C++:我需要手动排序结构字段以获得最佳性能吗?
【发布时间】:2015-01-29 17:07:19
【问题描述】:

我刚刚阅读了这篇关于指令和内存 CPU 缓存意识的文章:

http://www.research.scea.com/research/pdfs/GDC2003_Memory_Optimization_18Mar03.pdf

文章推理是围绕使用C/C++。

我有三个相关的问题:

  1. C# 通常会遵循相同的规则吗?

  2. 我是否需要手动排序结构字段以获得最佳性能?编译器会处理这个问题还是因为更高级别而无法处理?

  3. 如果是,那么这对通用结构有何影响?例如。 struct Triple { /.../ }

【问题讨论】:

    标签: c# c++ optimization struct memory-alignment


    【解决方案1】:

    C# 通常会遵循相同的规则吗?

    C# 与 C 和 C++ 存在相同的问题,即未对齐的结构会导致某些(可能是大多数)架构中的性能受到影响。

    我是否需要手动订购结构字段以获得最佳性能?编译器会处理这个问题还是因为更高级别而无法处理?

    虽然可能允许这样做,但实际上 Microsoft 编译器默认情况下不会处理此问题。结构的[StructLayout(LayoutKind.Auto)](这是默认值)通常与[StructLayout(LayoutKind.Sequential)] 相同。在 C 中,结构成员必须是连续的,而在 C# 中,它们也遵循此选择。

    当然,除此之外,编译器会尝试对齐结构成员,因为它们优化了性能而不是空间。您可能已经发现在您的特定场景中优化空间确实可以提高性能,但这对于编译器来说太复杂了。

    如果是,那么这对通用结构有何影响?例如。结构 三重 { /.../ }

    当您看到Triple<T1, T2, T3> 的定义时,您在代码中看到的就是所谓的(在 MSDN 中)泛型类型定义。每次实例化此泛型定义的类型参数的新组合时,环境都会创建一个新的运行时类型(您可能会看到它被称为 Triple'1)。生成的类型不再与非泛型类型不同,我认为 JIT 编译器没有理由区别对待它(但我当然可能是错的)。

    【讨论】:

    • 感谢您解决每个子问题。我问过泛型,因为我无法预测它是 int+string+array 还是 object-int-double,所以手动优化可能是不可能的?
    • @Den 哦,我明白了。恐怕没有简单的方法可以解决它。但也许,如果它非常重要,您可以创建多个结构,每个结构都有针对特定情况(值-值-值、值-值-引用等)优化的布局,让它们实现通用接口 ITriple<T1, T2, T3> 并制作一个工厂方法将获取该数据,选择接口的最佳实现并返回一个实例?但即使对于值类型,您也无法确定哪个更大 - int/double/int 与 double/int/int 不同,因此您最多也必须检查参数大小。
    【解决方案2】:

    默认情况下,.NET 可以随意订购类成员。我认为它会选择最佳布局,但我不确定。默认情况下,结构布局将具有与 C++ 中相同的布局语义。这些是 CLR 的属性,而不是 C#。

    您可以使用StructLayout 属性显式控制非托管布局:

    using System.Runtime.InteropServices;
    [StructLayout(LayoutKind.Explicit)]
    struct TestUnion 
    {
        [FieldOffset(0)] 
        public int i;
        [FieldOffset(0)] 
        public double d;
        [FieldOffset(0)] 
        public char c;
        [FieldOffset(0)] 
        public byte b1;
    }
    

    当然,一般建议是以最容易维护的方式布局代码。

    【讨论】:

    • 是的!我最初没有包含这个,因为我知道 C# 不能保证这一点。
    猜你喜欢
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2010-10-26
    • 2013-09-11
    相关资源
    最近更新 更多