在 C# 中创建内存对齐数组

BJu*_*ury 2 c#

我需要创建一个与 64 字节边界对齐的数组。我需要这样做,因为我正在调用一个使用AVX的 DLL ,这需要对齐数据。本质上我需要在 C# 中执行此操作:

void* ptr = _aligned_malloc(64 * 1024, 64);
int8_t* memory_ptr = (int8_t*)ptr;
Run Code Online (Sandbox Code Playgroud)

我很确定我无法在 C# 中自然地创建这样一个边界的数组。因此,一种选择是创建一个 x+64 长的字节数组,然后“创建”一个覆盖它的数组,但在所需边界处有一个偏移量。

问题是如何实现这一点,并且不会出现内存泄漏?(内存泄漏是我不想使用 DLL 创建对数组的引用并将其传递给 C# 的原因。除非有一个好的方法可以这样做?)


使用下面有用的答案,这就是我所拥有的,希望它对其他人有帮助:

public class Example : IDisposable
{
    private ulong memory_ptr;

    public unsafe Example() 
    {
        memory_ptr = (ulong)NativeMemory.AlignedAlloc(0x10000, 64);
    }

    public unsafe Span<byte> Memory => new Span<byte>((void*)memory_ptr, 0x10000);

    public unsafe void Dispose()
    {
        NativeMemory.Free((void*)memory_ptr);
    }
}
Run Code Online (Sandbox Code Playgroud)

Cha*_*ace 5

如前所述,.NET 6 有NativeMemory.AlignedAlloc. 您需要确保打电话,AlignedFree否则可能会发生泄漏。

void* a = default;
try
{
    a = NativeMemory.AlignedAlloc(size * sizeof(long), 64);
    var span = new Span<long>(a, size);
    // fill span
    // call DLL with span
}
finally
{
    NativeMemory.AlignedFree(a);
}
Run Code Online (Sandbox Code Playgroud)

固定GCHandle是旧版本 .NET 的另一种选择。然后,您需要使用以下代码计算起始对齐偏移量(在您的情况下alignment64

var ptr = (long)handle.AddrOfPinnedObject();
var offset = (int) ((ptr + alignment - 1) / alignment * alignment - ptr) / sizeof(long);
Run Code Online (Sandbox Code Playgroud)

同样,您需要确保handle.Free调用finally.