内存对齐理解

文章目录

CPU

内存对齐指的是对象首地址的位置是某个数值(alignment)的整数倍, 比如按4字节对齐,那么这个对象的首地址会是4的整数倍(0,4,8 …)。

假如一个对象要求按alignment对齐,那么我们如何保证其所在的内存地址就是alignment的整数倍?

  • 堆(malloc/new)
    下面的代码可以看到,new出来的地址是16的整数倍(malloc也一样,不过这里测试数据不严谨,应该说是max_align_t
    的整数倍,具体就可以翻阅malloc的文档),16的整数倍肯定也是Data的对齐属性8的整数倍,但是如果Data的对齐属性是32,那么new出来的内存首地址就不一定是32的整数倍,这里就需要开发者自己去实现malloc_align(), free_align(),当然gcc和msvc会有实现好的memalign(size, alignment)。
struct alignas(8) Data
{
    char i;
    char j;
    char k;
};

int main()
{
    Data* demo = new Data();
    std::cout << "Data align = " << alignof(Data) <<std::endl;
    std::cout << "Data size = " << sizeof(Data) <<std::endl;
    std::cout << "address of demo: " << (reinterpret_cast<uintptr_t>(demo)) % 16   << std::endl;
    std::cout << "address of demo: " << (reinterpret_cast<uintptr_t>(demo)) % 32   << std::endl;
}
//print
Data align = 8
Data size = 8
address of demo: 0
address of demo: 16

  • 根据下面的代码可以测试出来,当Data在栈上的时候,对象的首地址会是其对齐属性的整数倍,这个工作应该是编译器做的,所以一旦编译结束后地址应该就确定了。
struct alignas(512) Data
{
    char i;
    char j;
    char k;
};

int main()
{
    Data demo ;
    std::cout << "Data align = " << alignof(Data) <<std::endl;
    std::cout << "Data size = " << sizeof(Data) <<std::endl;
    std::cout << "address of demo: " << (reinterpret_cast<uintptr_t>(&demo)) % 512   << std::endl;
    std::cout << "address of demo: " << (reinterpret_cast<uintptr_t>(&demo)) % 1024   << std::endl;
}
// print
Data align = 512
Data size = 512
address of demo: 0
address of demo: 512

CPU数据结构

对于数据结构而言,

struct Test
{
	char a;
	int b;
	char c;
}

假如机器默认对齐值是4,那么偏移是[0,4,5]。现在问题来了,时候需要padding呢?其实padding多少是根据该类型的数组[1]的值确定的,主要是为了保证[1]的a,b,c还符合对齐规则,为此总结min(default, max_size(Test)), 这个玩意可以证明,数组[1]中的a,b,c都符合对齐规则,很神奇。这里Test的对齐值应该是4,所以sizeof(Test)=12, alignof(Test)=4.我们知道C++提供一个alignas去对类型设定。

struct alignas(1) Test
{
	char a;
	int b;
	char c;
}

根据上面推导我们知道,类型对齐值应该是4,但是这里强制设置了1,如果按照1去对其的话,数组[1]中的b偏移是13,这就不对,所以这里编译器还是会按4去设定,忽略程序员提供的错误信息。

struct alignas(8) Test
{
	char a;
	int b;
	char c;
}

当设定为8的时候,这里[1]中a的偏移是16,那么b的偏移是20符合偏移规则,所以8符合条件,那么编译器就会接受这个设定,所以alignof(Test)=8, sizeof(Test)=16。综上,对于结构体而言sizeof取决于数组[1]中的各个变量能否满足对齐规则,即使程序员强行指定,如果不符合的话编译器也不接受的。

GPU

cudaMalloc 类似于malloc,cudaMalloc的对齐地址是256。
类似于alignas ,cuda中使用__align__来给结构设定对其属性。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值