C# 与 C/C++:我是否需要手动对结构字段进行排序以获得最佳性能

本文关键字:字段 结构 排序 性能 最佳 C++ 是否 | 更新日期: 2023-09-27 18:32:34

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

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

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

我有三个相关问题:

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

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

  3. 如果是,那么这对泛型结构有何影响? 例如结构 三重 <T1,> {/.../}

C# 与 C/C++:我是否需要手动对结构字段进行排序以获得最佳性能

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

C# 与 C 和 C++ 具有相同的问题,因为未对齐的结构会导致某些(可能是大多数(体系结构中的性能受到影响。

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

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

当然,有了这个,编译器会尝试对齐结构成员,因为它们针对性能进行了优化,但不针对空间进行了优化。您可能已经发现,在您的特定方案中,优化空间确实可以提高性能,但这太复杂了,编译器无法推断。

如果是,那么这对泛型结构有何影响? 例如结构 三重<T1,> {/.../}

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

默认情况下,.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;
}

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