C# 结构体参数和局部变量默认对齐吗?

问题描述 投票:0回答:1

假设我有一个这样定义的结构:

[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)]
readonly struct Example {
    [FieldOffset(0)]
    public float A;
    [FieldOffset(4)]
    public float B;
    [FieldOffset(8)]
    public float C;
    [FieldOffset(12)]
    public float D;
}

Example
的本地实例和参数实例是否保证16字节对齐?

具体来说,我很好奇是否可以使用

Unsafe.As
将这样的结构重新解释为
Vector4

static void Test(Example e) {
    var vec4 = Unsafe.As<Example, Vector4>(ref e); // Is vec4 aligned?

    var e2 = new Example();
    vec4 = Unsafe.As<Example, Vector4>(ref e2); // Is vec4 aligned?
}
c# simd memory-alignment
1个回答
1
投票

结构类型的局部变量和参数不一定是“过度对齐”(即与标量代码所需的任何内容对齐)。

Example
不需要16的对齐,因此JIT编译器没有特定的动机来确保它得到它,当然它可能会发生,我必须稍微修改源代码以获得未对齐的地址(好吧,不是 16 对齐,从标量的角度来看它仍然足够对齐)。

这是实际中并未进行 16 对齐的屏幕截图:

为了实现这一点,我在

e
之前插入了另一个结构体参数,其大小为 8。

存在冗余移动,因为这是在未优化模式下发生的(模块加载时抑制 JIT 优化,这是调试的默认设置,但可以将其关闭以调试优化的代码,这有其自身的问题)。

但是,显然

Unsafe.As
产生的负载是未对齐的负载(
vmovupd
,理论上这是加载 2 个双精度向量而不是 4 个浮点数的向量的指令,但这没有实际区别),因此不会导致任何异常错位。我找不到关于以这种方式加载 Vector4
官方
需要什么样的对齐方式的明确文档。

© www.soinside.com 2019 - 2024. All rights reserved.