有没有一种方法可以将.NET对象的内存对齐到64字节?

3

在C和C++中有像_aligned_malloc这样的函数,但我找不到任何用于对.NET对象在内存中进行对齐的方法。


6
为什么要使用C#,但又关注内存层面的问题?高级语言的整个意义就在于将这些事情抽象化。 - mellamokb
5
C#是一种托管语言。CLR管理所有与内存有关的方面,因此您无需担心它们。 - dtb
1
.NET具有字段对齐属性。显然,它们提供了一些控制内存相关方面的功能。 - Nick Strupat
4
@Nick: 这是为了实现互操作性。这是你在这里做的吗? - Cody Gray
5
.NET 中的字段对齐属性仅用于通过 P/Invoke 与非托管代码进行交互。 - Adam Maras
一种方法是分配过多的内存,然后只使用最接近对齐部分的下一个部分。例如,如果您在0x..31处获得一个指针,则向上舍入为0x...40并使用它。(您需要自己考虑额外的大小。) - porges
2个回答

3
在一般情况下,无法有用地将一个 .net 对象对齐到 64 位边界,因为即使一个对象最初在 64 位边界上开始,也不能保证它不会被重定位到 32 位的奇数倍。由于某种原因,.net 似乎认为强制数组内包含大于一千个 double 值的向大对象堆分配空间是值得的,大对象堆总是 64 位对齐但是表现却很差,然而并没有提供有用的手段来请求其他对象的 64 位对齐方式,尽管这样做应该不难或不会过于昂贵(在 gen0 中上调对象大小;当将对象移动到更高的代数时,成对处理奇数大小的对象)。

0

更正 -- 您需要创建一个P/Invocable DLL,然后调用它来执行aligned_malloc函数。以下是示例C++代码:


#include <malloc.h>
extern "C" { __declspec(dllexport) void* alMlc(size_t size, size_t alginment) { return _aligned_malloc(size,alginment); } }

C# 代码(假设您创建的DLL名为mallocer.dll):


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication7 { class Program { [DllImport("mallocer.dll", CallingConvention=CallingConvention.Cdecl)] static extern IntPtr alMlc(int size, int alignment); static void Main(string[] args) { unsafe { //分配64字节的非托管内存,精确对齐到64字节 char* str = (char*)alMlc(64,64).ToPointer(); str[0] = 'H'; str[1] = 'i'; str[2] = '!'; str[3] = '\0';
Console.WriteLine(System.Runtime.InteropServices.Marshal.PtrToStringAuto(new IntPtr(str)));
} Console.ReadKey(); } } }

分配64字节的非托管内存,将其转换为char*类型,设置一些文本,并将其打印到屏幕上。确切地说,str变量被分配了64个字节的空间。 - bbosak
64字节对齐于64字节。 - bbosak
如果您使用的是64位CPU,int类型可能会变成long。 - bbosak
对于之前的评论感到抱歉:将数据对齐到64字节边界的原因可能是为了在后续调用AVX512指令时更加高效。如果我的记忆没有出错,以下断言可能完全不正确,而且我对此的记忆也有很大的潜在错误性,即CPU必须将非512位对齐的SIMD数据重新对齐到512位才能调用任何SIMD指令,从而破坏任何潜在的性能提升。对于AVX256(32字节对齐)等情况也是如此。 - CJPN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接