.Net 中的数据结构在内存中保持异构结构连续
Data structure in .Net keeping heterogeneous structs contiguous in memory
我正在寻找 .Net 中的数据结构,它使异构结构在内存中保持连续,以便 cpu-缓存友好。
此博客中解释了这种类型的数据结构:T-machine.org 在 迭代 4。
在 .Net 中,值类型(结构)数组使数据在内存中保持连续,但这仅适用于非泛型数组。
我试图创建一个 ValueType[]
,但结构被装箱了。所以引用在内存中是连续的,但不是真实数据。
经过多次尝试后,我认为这在 .Net 中是不可能的。我看到的唯一可能的解决方案是手动管理字节数组中结构的序列化和反序列化,但我认为它不会高效。
您找到本地解决方案了吗?还是我的更好的解决方案?
编辑 1:
我正在尝试实现 T-Machine.org 博客中描述的实体组件系统。
没有。在 C# 中无法执行 迭代 4。您无法决定 .NET struct
或 class
在内存中的位置。没有类似 Placement New of C++.
的内容
但请注意,即使是迭代 4,问题似乎也多于解决方案:
At this point, our iterations are quite good, but we’re seeing some recurring problems:
- Re-allocation of arrays when Components are added/removed (I’ve not covered this above – if you’re not familiar with the problem, google “C dynamic array”)
- Fragmentation (affects every iteration after Iteration 1, which doesn’t get any worse simple because it’s already as bad as it could be)
- Cross-referencing (which I skipped)
但是
如果你有 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 联合。但是通过使用 FixedLayout
和 FieldOffset
你可以创建它们。请注意,它们 与引用类型完全不兼容 ,显然 SuperStruct
的大小将是最大可能元素的大小。在这种情况下,32 字节,因为 Foo
是 20 字节,但它前后需要一些填充以对齐到 8 字节边界。
很明显,您的数组属于 SuperStruct
类型。请注意,按照 Iterion 4 示例,StructType
并不是绝对必要的,因为元素的类型已在其他地方编写。
我正在寻找 .Net 中的数据结构,它使异构结构在内存中保持连续,以便 cpu-缓存友好。
此博客中解释了这种类型的数据结构:T-machine.org 在 迭代 4。
在 .Net 中,值类型(结构)数组使数据在内存中保持连续,但这仅适用于非泛型数组。
我试图创建一个 ValueType[]
,但结构被装箱了。所以引用在内存中是连续的,但不是真实数据。
经过多次尝试后,我认为这在 .Net 中是不可能的。我看到的唯一可能的解决方案是手动管理字节数组中结构的序列化和反序列化,但我认为它不会高效。
您找到本地解决方案了吗?还是我的更好的解决方案?
编辑 1: 我正在尝试实现 T-Machine.org 博客中描述的实体组件系统。
没有。在 C# 中无法执行 迭代 4。您无法决定 .NET struct
或 class
在内存中的位置。没有类似 Placement New of C++.
但请注意,即使是迭代 4,问题似乎也多于解决方案:
At this point, our iterations are quite good, but we’re seeing some recurring problems:
- Re-allocation of arrays when Components are added/removed (I’ve not covered this above – if you’re not familiar with the problem, google “C dynamic array”)
- Fragmentation (affects every iteration after Iteration 1, which doesn’t get any worse simple because it’s already as bad as it could be)
- Cross-referencing (which I skipped)
但是
如果你有 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 联合。但是通过使用 FixedLayout
和 FieldOffset
你可以创建它们。请注意,它们 与引用类型完全不兼容 ,显然 SuperStruct
的大小将是最大可能元素的大小。在这种情况下,32 字节,因为 Foo
是 20 字节,但它前后需要一些填充以对齐到 8 字节边界。
很明显,您的数组属于 SuperStruct
类型。请注意,按照 Iterion 4 示例,StructType
并不是绝对必要的,因为元素的类型已在其他地方编写。