【问题标题】:Data structure in .Net keeping heterogeneous structs contiguous in memory.Net 中的数据结构使异构结构在内存中保持连续
【发布时间】:2015-05-03 08:37:20
【问题描述】:

我正在寻找 .Net 中的一种数据结构,它使异构结构在内存中保持连续,以便对 cpu-cache 友好。

这种类型的数据结构在此博客中进行了解释:T-machine.org迭代 4

在 .Net 中,值类型(结构)数组使数据在内存中保持连续,但这仅适用于非泛型数组。 我试图创建一个ValueType[],但结构是装箱的。所以引用在内存中是连续的,而不是真实的数据。

经过多次尝试,我认为这在 .Net 中是不可能的。我看到的唯一可能的解决方案是手动管理字节数组中结构的序列化和反序列化,但我认为它不会高效。

您找到本地解决方案了吗?还是我的更好的解决方案?

编辑 1: 我正在尝试实现T-Machine.org 博客中描述的实体组件系统。

【问题讨论】:

  • 如果你需要的数据结构的类型是固定的,你可以把它们放在另一个结构中......所以struct PositionVelocity { Position Pos; Velocity Vel }
  • 您可以使用两个不同的数组,这也可以减少填充,如果不是“大结构”的所有字段都同样热,那就特别好。无论如何,你能提供更多关于你在做什么的细节吗?然后我们可以给出一个更有针对性的解决方案。
  • @xanatos 不幸的是,我在编译时不知道所有结构类型。此外,我可以有一个位置,然后是一个速度,然后是另一个速度。

标签: c# .net data-structures cpu-cache


【解决方案1】:

没有。没有办法在 C# 中执行 Iteration 4。您无法决定将 .NET structclass 放在内存中的哪个位置。没有类似Placement New of C++的东西。

但请注意,即使是第 4 次迭代,问题似乎也多于解决方案:

在这一点上,我们的迭代非常好,但我们看到了一些反复出现的问题:

  • 在添加/删除组件时重新分配数组(我没有在上面介绍过 - 如果您不熟悉该问题,请搜索“C 动态数组”)
  • 碎片化(影响迭代 1 之后的每次迭代,这不会变得更糟,因为它已经很糟糕了)
  • 交叉引用(我跳过了)

但是

如果struct 大小差不多,union 技巧就足够了...

public enum StructType
{
    Velocity = 0,
    Position = 1,
    Foo = 2,
    Bar = 3,
}

public struct Velocity
{
    public int Vx;
    public int Vy;
}

public struct Position
{
    public int X;
    public int Y;
    public int Z;
}

public struct Foo
{
    public double Weight;
    public double Height;
    public int Age;
}

public struct Bar
{
    public int ColorR;
    public int ColorG;
    public int ColorB;
    public int Transparency;
}

[StructLayout(LayoutKind.Explicit)]
public struct SuperStruct
{
    [FieldOffset(0)]
    public StructType StructType;

    [FieldOffset(4)]
    public Velocity Velocity;

    [FieldOffset(4)]
    public Position Position;

    [FieldOffset(4)]
    public Foo Foo;

    [FieldOffset(4)]
    public Bar Bar;
}

“官方”在 C# 中没有 C 联合。但是通过使用FixedLayoutFieldOffset,您可以创建它们。请注意,它们与引用类型完全不兼容,显然SuperStruct 的大小将是最大可能元素的大小。在本例中为 32 字节,因为 Foo 为 20 字节,但在其前后需要一些填充以对齐 8 字节边界。

显然,您的数组将是 SuperStruct 类型。请注意,按照 Iterion 4 示例,StructType 并不是绝对必要的,因为元素的类型写在其他地方。

【讨论】:

  • 谢谢,我就是这么想的,但我不能 100% 确定。我想我会使用多个数组,每个结构类型一个。这样做我将有缓存未命中(当访问系统中的多个组件类型时),但少于组件作为类。
  • @Romain 等等...等等...如果您只需要保留非引用类型,您可以使用联合技巧。给我五分钟……
  • 如果它们的大小不同,那会浪费空间
  • @Romain 查看示例。
  • @harold 显然 :-) 这不是完美的魔法子弹。如果您有各种大小相似的struct,它就可以工作。
猜你喜欢
  • 2012-04-10
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多