结构布局优化

Dav*_*rey 2 c# opengl optimization structure

字节优化给你带来多大的性能提升(使它们成为8,32,64等的倍数......)?

这是一个示例结构:

[StructLayout(LayoutKind.Explicit)]
public struct RenderItem
{
   [FieldOffset(0)] byte[] mCoordinates = new byte[3]; //(x,y,z)
   [FieldOffset(3)] short  mUnitType;            

}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,做这样的事情有多重要:

[StructLayout(LayoutKind.Explicit)]
public struct RenderItem
{
   [FieldOffset(0)] byte[] mCoordinates = new byte[3]; //(x,y,z)
   [FieldOffset(4)] short  mUnitType;
   [FieldOffset(6)] byte[] mPadding = new byte[2];     //make total to 8 bytes

}
Run Code Online (Sandbox Code Playgroud)

我敢肯定它是那些"随尺寸扩展"的东西之一,所以特别是我很好奇这个结构会被用来创建一个VertexBuffer对象大约150,000次:

//int objType[,,] 3 dimensional int with object type information stored in it

int i = 0;
RenderItem vboItems[16 * 16 * 16 * 36]  //x - 16, y - 16, z - 16, 36 verticies per object

For(int x = 0; x < 16; x++)
{
     For(int y = 0; y < 16; y++)
     {
          For(int z = 0; z < 16; z++)
          {
               vboItems[i++] = (x,y,z,objType[x,y,z]);
          }
     }
 }

 //Put vboItems into a VBO
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 12

我假设您应用了[MarshalAs]属性来使数组成为ByValArray,这只是对这样的结构有意义的事情.实际上,通过使结构2字节更大来使它变慢.那将使用处理器的缓存效率较低,在阵列中使用它们时结构更少,这对于perf来说非常重要.

默认的StructLayoutAttribute.Pack值8已经过优化,以提供最佳的结构布局.它实际上对您的结构没有任何影响,无论Pack值如何,成员都已经以最佳方式对齐.任何现代处理器获得最佳性能的规则:

  • 成员应该与可以被成员大小整除的地址对齐.这可能会在成员之间添加填充字节.此规则可防止处理器必须从存储器读取中复用字节值或执行两次读取并将字节粘合在一起.在你的结构上不是问题,唯一需要对齐的成员是mUnitType,它必须在2处对齐并且它已经在4处对齐.还要注意你不必使用[FieldOffset],默认布局已经很好了.

  • 在数组中使用struct时,应该正确对齐成员.这可能会在结构的末尾添加打包,以使数组中的下一个元素正确对齐.同样不是你的结构上的问题,它是6个字节长,所以数组中的下一个元素将使其mUnitType对齐,因为它只需要2.如果你实际上声明了没有[MarshalAs]的数组,那么抖动将自动添加2个字节没有你的帮助填充,以确保数组指针正确对齐.

  • 成员不应该跨越cpu缓存行.在我所知的任何现代处理器上都是64字节.对于perf非常不利,cpu必须读取两个缓存行的数据并始终将字节粘合在一起,perf hit大约x3慢.当结构包含大小为8或更大的成员时,这可能发生在32位计算机上.所以长,双或小数.不仅成员的对齐很重要,而且结构也在内存中分配.这在x86版本的.NET上有点问题,它只能保证起始地址与从堆栈或GC堆分配的数据的4的倍数对齐.不是x64的问题.并不是你的struct的问题,它只包含永远不会跨越cpu缓存行的小成员.

因此,通过这些规则,您无需提供帮助,即使没有LayoutKind.Explicit,结构也已经是最优的.

另一个考虑适用,一个与对齐没有任何关系.甲不是32位或64位处理器的最优的数据类型.如果您执行除简单加载和存储之外的任何操作,则需要额外的开销将其从16位转换为32位.这背后的背景故事就在这里.您现在需要在更低效的操作之间平衡更好的CPU缓存使用,这是您只能使用分析器可靠地执行的操作.